Add customization screens for stocks and indices with on-screen keyboard

- Stock ticker customization with QWERTY keyboard input (up to 5 tickers)
- Index selection from scrollable multi-select list (up to 5 indices)
- Friendly index names displayed (S&P 500, Dow Jones, NASDAQ, etc.)
- CUSTOMIZE button in dashboard footer
- Config persisted to ESP32 Preferences
- REFRESHING... message shown when returning from customization
- Auto-refresh every 5 minutes
This commit is contained in:
Chad 2026-03-29 18:51:03 -05:00
parent 99fd266b47
commit fcde8cf66b

View file

@ -1,6 +1,7 @@
/** /**
* Bitcoin Dashboard for Elecrow 7-inch HMI Display * Bitcoin Dashboard for Elecrow 7-inch HMI Display
* Three-column layout with antialiased fonts * Three-column layout with antialiased fonts
* Customization screen for stocks and indices
*/ */
#include <Arduino.h> #include <Arduino.h>
@ -22,6 +23,12 @@
#define TFT_GOLD 0xFEA0 #define TFT_GOLD 0xFEA0
#define TFT_SILVER 0xC618 #define TFT_SILVER 0xC618
#define TFT_GREEN 0x07E0 #define TFT_GREEN 0x07E0
#define TFT_DARKGRAY 0x2104
#define TFT_GRAY 0x8410
#define MAX_STOCKS 5
#define MAX_INDICES 5
#define MAX_TICKER_LEN 8
class LGFX : public lgfx::LGFX_Device { class LGFX : public lgfx::LGFX_Device {
public: public:
@ -114,12 +121,51 @@ static LGFX lcd;
static Preferences preferences; static Preferences preferences;
double btcPrice = 0, goldPrice = 0, silverPrice = 0; double btcPrice = 0, goldPrice = 0, silverPrice = 0;
double mstrPrice = 0, strtPrice = 0; double stockPrices[MAX_STOCKS] = {0};
double nasdaqPrice = 0, dowPrice = 0, spxPrice = 0; double indexPrices[MAX_INDICES] = {0};
char stockTickers[MAX_STOCKS][MAX_TICKER_LEN + 1] = {"MSTR", "STRC", "", "", ""};
char indexTickers[MAX_INDICES][MAX_TICKER_LEN + 1] = {"^IXIC", "^DJI", "^GSPC", "", ""};
bool indexSelected[MAX_INDICES] = {true, true, true, false, false};
const char* availableIndices[] = {
"^GSPC", "^DJI", "^IXIC", "^RUT", "^VIX",
"^FTSE", "^GDAXI", "^FCHI", "^N225", "^HSI",
"^AXJO", "^KS11", "^TWII", "^STI", "^MXX"
};
const char* indexNames[] = {
"S&P 500", "Dow Jones", "NASDAQ", "Russell 2000", "VIX",
"FTSE 100", "DAX", "CAC 40", "Nikkei 225", "Hang Seng",
"ASX 200", "KOSPI", "Taiwan Weighted", "Straits Times", "IPC Mexico"
};
const int numAvailableIndices = 15;
const char* getIndexFriendlyName(const char* ticker) {
for (int i = 0; i < numAvailableIndices; i++) {
if (strcmp(ticker, availableIndices[i]) == 0) {
return indexNames[i];
}
}
return ticker;
}
unsigned long lastRefresh = 0; unsigned long lastRefresh = 0;
const unsigned long REFRESH_INTERVAL = 300000; const unsigned long REFRESH_INTERVAL = 300000;
enum ScreenState {
SCREEN_DASHBOARD,
SCREEN_CUSTOMIZE_STOCKS,
SCREEN_CUSTOMIZE_INDICES
};
ScreenState currentScreen = SCREEN_DASHBOARD;
int selectedStockSlot = -1;
int selectedIndexSlot = -1;
char keyboardBuffer[MAX_TICKER_LEN + 1] = "";
int keyboardPos = 0;
int indexScrollOffset = 0;
bool needsRefresh = false;
String formatPriceUS(double price, int decimals = 2, bool includeDollar = true) { String formatPriceUS(double price, int decimals = 2, bool includeDollar = true) {
if (price <= 0) return "..."; if (price <= 0) return "...";
@ -183,16 +229,216 @@ bool fetchPrice(const char* symbol, double* result) {
return true; return true;
} }
void loadConfig() {
preferences.begin("dashboard", true);
for (int i = 0; i < MAX_STOCKS; i++) {
String key = "stock" + String(i);
String val = preferences.getString(key.c_str(), "");
if (val.length() > 0 && val.length() <= MAX_TICKER_LEN) {
strcpy(stockTickers[i], val.c_str());
}
}
for (int i = 0; i < MAX_INDICES; i++) {
String key = "index" + String(i);
String val = preferences.getString(key.c_str(), "");
if (val.length() > 0 && val.length() <= MAX_TICKER_LEN) {
strcpy(indexTickers[i], val.c_str());
indexSelected[i] = true;
}
}
preferences.end();
}
void saveConfig() {
preferences.begin("dashboard", false);
for (int i = 0; i < MAX_STOCKS; i++) {
String key = "stock" + String(i);
preferences.putString(key.c_str(), stockTickers[i]);
}
for (int i = 0; i < MAX_INDICES; i++) {
String key = "index" + String(i);
if (indexSelected[i]) {
preferences.putString(key.c_str(), indexTickers[i]);
} else {
preferences.putString(key.c_str(), "");
}
}
preferences.end();
}
void updatePrices() { void updatePrices() {
if (WiFi.status() != WL_CONNECTED) return; if (WiFi.status() != WL_CONNECTED) return;
fetchPrice("BTC-USD", &btcPrice); fetchPrice("BTC-USD", &btcPrice);
fetchPrice("GC=F", &goldPrice); fetchPrice("GC=F", &goldPrice);
fetchPrice("SI=F", &silverPrice); fetchPrice("SI=F", &silverPrice);
fetchPrice("MSTR", &mstrPrice);
fetchPrice("STRC", &strtPrice); for (int i = 0; i < MAX_STOCKS; i++) {
fetchPrice("^IXIC", &nasdaqPrice); if (strlen(stockTickers[i]) > 0) {
fetchPrice("^DJI", &dowPrice); fetchPrice(stockTickers[i], &stockPrices[i]);
fetchPrice("^GSPC", &spxPrice); }
}
for (int i = 0; i < MAX_INDICES; i++) {
if (indexSelected[i] && strlen(indexTickers[i]) > 0) {
fetchPrice(indexTickers[i], &indexPrices[i]);
}
}
}
void drawKeyboard(int y) {
const char* rows[] = {
"QWERTYUIOP",
"ASDFGHJKL",
"ZXCVBNM",
"1234567890"
};
const int numRows = 4;
const int keySize = 32;
const int keyGap = 2;
for (int r = 0; r < numRows; r++) {
int rowLen = strlen(rows[r]);
int rowWidth = rowLen * (keySize + keyGap) - keyGap;
int startX = (SCREEN_WIDTH - rowWidth) / 2;
int keyY = y + r * (keySize + keyGap);
for (int k = 0; k < rowLen; k++) {
int keyX = startX + k * (keySize + keyGap);
lcd.fillSmoothRoundRect(keyX, keyY, keySize, keySize, 4, TFT_DARKGRAY);
lcd.setTextColor(TFT_WHITE, TFT_DARKGRAY);
lcd.setFont(&fonts::DejaVu12);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawChar(rows[r][k], keyX + keySize/2, keyY + keySize/2);
}
}
int btnY = y + numRows * (keySize + keyGap) + 4;
int delX = SCREEN_WIDTH / 2 - 125;
int enterX = SCREEN_WIDTH / 2 + 5;
lcd.fillSmoothRoundRect(delX, btnY, 120, 32, 6, TFT_ORANGE);
lcd.setTextColor(TFT_WHITE, TFT_ORANGE);
lcd.setFont(&fonts::DejaVu18);
lcd.drawString("DEL", delX + 60, btnY + 16);
lcd.fillSmoothRoundRect(enterX, btnY, 120, 32, 6, TFT_GREEN);
lcd.setTextColor(TFT_WHITE, TFT_GREEN);
lcd.drawString("SAVE", enterX + 60, btnY + 16);
}
void drawStockCustomizeScreen() {
lcd.fillScreen(TFT_BLACK);
lcd.fillSmoothRoundRect(0, 0, SCREEN_WIDTH, 50, 8, TFT_ORANGE);
lcd.setTextColor(TFT_WHITE, TFT_ORANGE);
lcd.setFont(&fonts::DejaVu24);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("CUSTOMIZE STOCKS (up to 5)", SCREEN_WIDTH / 2, 25);
int slotY = 60;
int slotHeight = 36;
for (int i = 0; i < MAX_STOCKS; i++) {
int y = slotY + i * (slotHeight + 8);
uint16_t bgColor = (selectedStockSlot == i) ? TFT_ORANGE : TFT_DARKGRAY;
lcd.fillSmoothRoundRect(200, y, 400, slotHeight, 6, bgColor);
lcd.setTextColor(TFT_WHITE, bgColor);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_left);
lcd.drawString(String(i + 1) + ":", 210, y + slotHeight/2);
lcd.setTextDatum(textdatum_t::middle_center);
String displayText;
if (selectedStockSlot == i) {
displayText = String(keyboardBuffer);
if (displayText.length() == 0) displayText = "_";
} else {
displayText = strlen(stockTickers[i]) > 0 ? String(stockTickers[i]) : "(tap to edit)";
}
lcd.drawString(displayText, 400, y + slotHeight/2);
}
drawKeyboard(slotY + MAX_STOCKS * (slotHeight + 8) + 20);
lcd.fillSmoothRoundRect(20, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY);
lcd.setTextColor(TFT_WHITE, TFT_GRAY);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("BACK", 95, SCREEN_HEIGHT - 30);
lcd.fillSmoothRoundRect(SCREEN_WIDTH - 170, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GREEN);
lcd.setTextColor(TFT_WHITE, TFT_GREEN);
lcd.drawString("INDICES >", SCREEN_WIDTH - 95, SCREEN_HEIGHT - 30);
}
void drawIndexCustomizeScreen() {
lcd.fillScreen(TFT_BLACK);
lcd.fillSmoothRoundRect(0, 0, SCREEN_WIDTH, 50, 8, TFT_ORANGE);
lcd.setTextColor(TFT_WHITE, TFT_ORANGE);
lcd.setFont(&fonts::DejaVu24);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("CUSTOMIZE INDICES (select up to 5)", SCREEN_WIDTH / 2, 25);
int listY = 60;
int itemHeight = 40;
int visibleItems = 8;
for (int i = 0; i < visibleItems; i++) {
int idx = indexScrollOffset + i;
if (idx >= numAvailableIndices) break;
int y = listY + i * (itemHeight + 4);
bool isSelected = false;
for (int j = 0; j < MAX_INDICES; j++) {
if (indexSelected[j] && strcmp(indexTickers[j], availableIndices[idx]) == 0) {
isSelected = true;
break;
}
}
uint16_t bgColor = isSelected ? TFT_GREEN : TFT_DARKGRAY;
lcd.fillSmoothRoundRect(150, y, 500, itemHeight, 6, bgColor);
lcd.setTextColor(TFT_WHITE, bgColor);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_left);
lcd.drawString(indexNames[idx], 170, y + itemHeight/2);
if (isSelected) {
lcd.setTextDatum(textdatum_t::middle_right);
lcd.drawString("SELECTED", 630, y + itemHeight/2);
}
}
if (indexScrollOffset > 0) {
lcd.fillSmoothRoundRect(380, listY - 30, 40, 24, 4, TFT_GRAY);
lcd.setTextColor(TFT_WHITE, TFT_GRAY);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("^", 400, listY - 18);
}
if (indexScrollOffset + visibleItems < numAvailableIndices) {
lcd.fillSmoothRoundRect(380, listY + visibleItems * (itemHeight + 4) + 8, 40, 24, 4, TFT_GRAY);
lcd.setTextColor(TFT_WHITE, TFT_GRAY);
lcd.drawString("v", 400, listY + visibleItems * (itemHeight + 4) + 20);
}
lcd.fillSmoothRoundRect(20, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY);
lcd.setTextColor(TFT_WHITE, TFT_GRAY);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("SAVE", 95, SCREEN_HEIGHT - 30);
lcd.fillSmoothRoundRect(SCREEN_WIDTH - 170, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY);
lcd.drawString("CANCEL", SCREEN_WIDTH - 95, SCREEN_HEIGHT - 30);
} }
void drawDashboard() { void drawDashboard() {
@ -210,7 +456,7 @@ void drawDashboard() {
int col2X = 280; int col2X = 280;
int col3X = 540; int col3X = 540;
int labelY = 60; int labelY = 60;
int priceY = labelY + 32; int priceY = labelY + 28;
lcd.setTextColor(TFT_ORANGE, TFT_BLACK); lcd.setTextColor(TFT_ORANGE, TFT_BLACK);
lcd.setFont(&fonts::Roboto_Thin_24); lcd.setFont(&fonts::Roboto_Thin_24);
@ -218,37 +464,247 @@ void drawDashboard() {
lcd.drawString(formatPriceUS(btcPrice, 0), col1X, priceY); lcd.drawString(formatPriceUS(btcPrice, 0), col1X, priceY);
lcd.setTextColor(TFT_GOLD, TFT_BLACK); lcd.setTextColor(TFT_GOLD, TFT_BLACK);
lcd.drawString("Gold:", col1X, labelY + 70); lcd.drawString("Gold:", col1X, labelY + 65);
lcd.drawString(formatPriceUS(goldPrice, 2), col1X, priceY + 70); lcd.drawString(formatPriceUS(goldPrice, 2), col1X, priceY + 65);
lcd.setTextColor(TFT_SILVER, TFT_BLACK); lcd.setTextColor(TFT_SILVER, TFT_BLACK);
lcd.drawString("Silver:", col1X, labelY + 140); lcd.drawString("Silver:", col1X, labelY + 130);
lcd.drawString(formatPriceUS(silverPrice, 2), col1X, priceY + 140); lcd.drawString(formatPriceUS(silverPrice, 2), col1X, priceY + 130);
lcd.setTextColor(TFT_GREEN, TFT_BLACK); lcd.setTextColor(TFT_GREEN, TFT_BLACK);
lcd.drawString("MSTR:", col2X, labelY); int stockY = labelY;
lcd.drawString(formatPriceUS(mstrPrice, 2), col2X, priceY); for (int i = 0; i < MAX_STOCKS; i++) {
if (strlen(stockTickers[i]) > 0) {
lcd.drawString(String(stockTickers[i]) + ":", col2X, stockY);
lcd.drawString(formatPriceUS(stockPrices[i], 2), col2X, stockY + 28);
stockY += 65;
}
}
lcd.drawString("STRC:", col2X, labelY + 70); lcd.setTextColor(TFT_WHITE, TFT_BLACK);
lcd.drawString(formatPriceUS(strtPrice, 2), col2X, priceY + 70); int indexY = labelY;
for (int i = 0; i < MAX_INDICES; i++) {
lcd.drawString("NASDAQ:", col3X, labelY); if (indexSelected[i] && strlen(indexTickers[i]) > 0) {
lcd.drawString(formatPriceUS(nasdaqPrice, 2), col3X, priceY); lcd.drawString(String(getIndexFriendlyName(indexTickers[i])) + ":", col3X, indexY);
lcd.drawString(formatPriceUS(indexPrices[i], 2), col3X, indexY + 28);
lcd.drawString("DOW:", col3X, labelY + 70); indexY += 65;
lcd.drawString(formatPriceUS(dowPrice, 2), col3X, priceY + 70); }
}
lcd.drawString("SPX:", col3X, labelY + 140);
lcd.drawString(formatPriceUS(spxPrice, 2), col3X, priceY + 140);
lcd.fillSmoothRoundRect(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, 40, 8, TFT_ORANGE); lcd.fillSmoothRoundRect(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, 40, 8, TFT_ORANGE);
lcd.setTextColor(TFT_WHITE, TFT_ORANGE); lcd.setTextColor(TFT_WHITE, TFT_ORANGE);
lcd.setFont(&fonts::DejaVu18); lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_left); lcd.setTextDatum(textdatum_t::middle_left);
String wifiStatus = WiFi.status() == WL_CONNECTED ? "Connected" : "DISCONNECTED"; String wifiStatus = WiFi.status() == WL_CONNECTED ? "OK" : "OFFLINE";
lcd.drawString("WiFi: " + wifiStatus, 20, SCREEN_HEIGHT - 20); lcd.drawString("WiFi: " + wifiStatus, 20, SCREEN_HEIGHT - 20);
lcd.fillSmoothRoundRect(SCREEN_WIDTH - 160, SCREEN_HEIGHT - 36, 140, 32, 6, TFT_DARKGRAY);
lcd.setTextDatum(textdatum_t::middle_center); lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("TOUCH TO REFRESH", SCREEN_WIDTH / 2, SCREEN_HEIGHT - 20); lcd.drawString("CUSTOMIZE", SCREEN_WIDTH - 90, SCREEN_HEIGHT - 20);
}
bool handleKeyboardTouch(int32_t x, int32_t y, int keyboardY) {
const char* rows[] = {
"QWERTYUIOP",
"ASDFGHJKL",
"ZXCVBNM",
"1234567890"
};
const int numRows = 4;
const int keySize = 32;
const int keyGap = 2;
for (int r = 0; r < numRows; r++) {
int rowLen = strlen(rows[r]);
int rowWidth = rowLen * (keySize + keyGap) - keyGap;
int startX = (SCREEN_WIDTH - rowWidth) / 2;
int keyY = keyboardY + r * (keySize + keyGap);
for (int k = 0; k < rowLen; k++) {
int keyX = startX + k * (keySize + keyGap);
if (x >= keyX && x < keyX + keySize && y >= keyY && y < keyY + keySize) {
if (keyboardPos < MAX_TICKER_LEN) {
keyboardBuffer[keyboardPos++] = rows[r][k];
keyboardBuffer[keyboardPos] = '\0';
}
return true;
}
}
}
int btnY = keyboardY + numRows * (keySize + keyGap) + 4;
int delX = SCREEN_WIDTH / 2 - 125;
int enterX = SCREEN_WIDTH / 2 + 5;
if (x >= delX && x < delX + 120 && y >= btnY && y < btnY + 32) {
if (keyboardPos > 0) {
keyboardPos--;
keyboardBuffer[keyboardPos] = '\0';
}
return true;
}
if (x >= enterX && x < enterX + 120 && y >= btnY && y < btnY + 32) {
if (selectedStockSlot >= 0) {
strcpy(stockTickers[selectedStockSlot], keyboardBuffer);
selectedStockSlot = -1;
keyboardPos = 0;
keyboardBuffer[0] = '\0';
}
return true;
}
return false;
}
bool handleStockCustomizeTouch(int32_t x, int32_t y) {
int slotY = 60;
int slotHeight = 36;
if (x >= 20 && x < 170 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
if (selectedStockSlot >= 0 && keyboardPos > 0) {
strcpy(stockTickers[selectedStockSlot], keyboardBuffer);
}
saveConfig();
currentScreen = SCREEN_DASHBOARD;
needsRefresh = true;
return true;
}
if (x >= SCREEN_WIDTH - 170 && x < SCREEN_WIDTH - 20 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
if (selectedStockSlot >= 0 && keyboardPos > 0) {
strcpy(stockTickers[selectedStockSlot], keyboardBuffer);
}
saveConfig();
currentScreen = SCREEN_CUSTOMIZE_INDICES;
indexScrollOffset = 0;
return true;
}
for (int i = 0; i < MAX_STOCKS; i++) {
int sy = slotY + i * (slotHeight + 8);
if (x >= 200 && x < 600 && y >= sy && y < sy + slotHeight) {
if (selectedStockSlot >= 0 && selectedStockSlot != i && keyboardPos > 0) {
strcpy(stockTickers[selectedStockSlot], keyboardBuffer);
}
selectedStockSlot = i;
strcpy(keyboardBuffer, stockTickers[i]);
keyboardPos = strlen(keyboardBuffer);
return true;
}
}
if (selectedStockSlot >= 0) {
int keyboardY = slotY + MAX_STOCKS * (slotHeight + 8) + 20;
if (handleKeyboardTouch(x, y, keyboardY)) {
return true;
}
}
return false;
}
bool handleIndexCustomizeTouch(int32_t x, int32_t y) {
int listY = 60;
int itemHeight = 40;
int visibleItems = 8;
if (x >= 20 && x < 170 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
saveConfig();
currentScreen = SCREEN_DASHBOARD;
needsRefresh = true;
return true;
}
if (x >= SCREEN_WIDTH - 170 && x < SCREEN_WIDTH - 20 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
currentScreen = SCREEN_DASHBOARD;
loadConfig();
return true;
}
if (x >= 380 && x < 420 && y >= listY - 30 && y < listY - 6) {
if (indexScrollOffset > 0) {
indexScrollOffset--;
}
return true;
}
if (x >= 380 && x < 420 && y >= listY + visibleItems * (itemHeight + 4) + 8 && y < listY + visibleItems * (itemHeight + 4) + 32) {
if (indexScrollOffset + visibleItems < numAvailableIndices) {
indexScrollOffset++;
}
return true;
}
for (int i = 0; i < visibleItems; i++) {
int idx = indexScrollOffset + i;
if (idx >= numAvailableIndices) break;
int iy = listY + i * (itemHeight + 4);
if (x >= 150 && x < 650 && y >= iy && y < iy + itemHeight) {
bool alreadySelected = false;
int selectedSlot = -1;
for (int j = 0; j < MAX_INDICES; j++) {
if (indexSelected[j] && strcmp(indexTickers[j], availableIndices[idx]) == 0) {
alreadySelected = true;
selectedSlot = j;
break;
}
}
if (alreadySelected) {
indexSelected[selectedSlot] = false;
indexTickers[selectedSlot][0] = '\0';
} else {
int count = 0;
for (int j = 0; j < MAX_INDICES; j++) {
if (indexSelected[j]) count++;
}
if (count < MAX_INDICES) {
for (int j = 0; j < MAX_INDICES; j++) {
if (!indexSelected[j]) {
strcpy(indexTickers[j], availableIndices[idx]);
indexSelected[j] = true;
break;
}
}
}
}
return true;
}
}
return false;
}
void showRefreshingMessage() {
lcd.fillSmoothRoundRect(0, SCREEN_HEIGHT - 40, SCREEN_WIDTH, 40, 8, TFT_ORANGE);
lcd.setTextColor(TFT_WHITE, TFT_ORANGE);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("REFRESHING...", SCREEN_WIDTH / 2, SCREEN_HEIGHT - 20);
}
void refreshDataAndShow() {
drawDashboard();
showRefreshingMessage();
updatePrices();
lastRefresh = millis();
drawDashboard();
}
bool handleDashboardTouch(int32_t x, int32_t y) {
if (x >= SCREEN_WIDTH - 160 && x < SCREEN_WIDTH - 20 && y >= SCREEN_HEIGHT - 36 && y < SCREEN_HEIGHT - 4) {
currentScreen = SCREEN_CUSTOMIZE_STOCKS;
selectedStockSlot = -1;
keyboardPos = 0;
keyboardBuffer[0] = '\0';
return true;
}
return true;
} }
void setup() { void setup() {
@ -273,6 +729,8 @@ void setup() {
lcd.setFont(&fonts::DejaVu18); lcd.setFont(&fonts::DejaVu18);
lcd.drawString("Starting...", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); lcd.drawString("Starting...", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
loadConfig();
preferences.begin("wifi", true); preferences.begin("wifi", true);
String ssid = preferences.getString("ssid", ""); String ssid = preferences.getString("ssid", "");
String pass = preferences.getString("password", ""); String pass = preferences.getString("password", "");
@ -314,21 +772,45 @@ void setup() {
void loop() { void loop() {
int32_t x, y; int32_t x, y;
if (lcd.getTouch(&x, &y)) { if (needsRefresh && currentScreen == SCREEN_DASHBOARD) {
lcd.setTextColor(TFT_WHITE, TFT_BLACK); needsRefresh = false;
lcd.setFont(&fonts::DejaVu24); drawDashboard();
lcd.setTextDatum(textdatum_t::middle_center); refreshDataAndShow();
lcd.fillRect(0, SCREEN_HEIGHT / 2 - 20, SCREEN_WIDTH, 40, TFT_BLACK); }
lcd.drawString("Refreshing...", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
if (lcd.getTouch(&x, &y)) {
switch (currentScreen) {
case SCREEN_DASHBOARD:
handleDashboardTouch(x, y);
break;
case SCREEN_CUSTOMIZE_STOCKS:
handleStockCustomizeTouch(x, y);
break;
case SCREEN_CUSTOMIZE_INDICES:
handleIndexCustomizeTouch(x, y);
break;
}
if (!needsRefresh) {
switch (currentScreen) {
case SCREEN_DASHBOARD:
updatePrices(); updatePrices();
lastRefresh = millis(); lastRefresh = millis();
drawDashboard(); drawDashboard();
break;
delay(500); case SCREEN_CUSTOMIZE_STOCKS:
drawStockCustomizeScreen();
break;
case SCREEN_CUSTOMIZE_INDICES:
drawIndexCustomizeScreen();
break;
}
} }
if (millis() - lastRefresh > REFRESH_INTERVAL) { delay(300);
}
if (currentScreen == SCREEN_DASHBOARD && millis() - lastRefresh > REFRESH_INTERVAL) {
updatePrices(); updatePrices();
lastRefresh = millis(); lastRefresh = millis();
drawDashboard(); drawDashboard();