further webserver idle screen tweaks
This commit is contained in:
parent
2c24ee3f81
commit
d02e2e5b5e
@ -282,7 +282,7 @@ void HomeActivity::render() {
|
|||||||
if (strlen(SETTINGS.pinnedListName) > 0) {
|
if (strlen(SETTINGS.pinnedListName) > 0) {
|
||||||
listsLabel = std::string(SETTINGS.pinnedListName);
|
listsLabel = std::string(SETTINGS.pinnedListName);
|
||||||
} else {
|
} else {
|
||||||
listsLabel = "ReadingLists";
|
listsLabel = "Reading Lists";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build menu items dynamically (need count for layout calculation)
|
// Build menu items dynamically (need count for layout calculation)
|
||||||
|
|||||||
@ -72,7 +72,7 @@ void CrossPointWebServerActivity::onEnter() {
|
|||||||
connectedIP.clear();
|
connectedIP.clear();
|
||||||
connectedSSID.clear();
|
connectedSSID.clear();
|
||||||
lastHandleClientTime = 0;
|
lastHandleClientTime = 0;
|
||||||
currentScreen = FileTransferScreen::WEB_BROWSER;
|
currentScreen = FileTransferScreen::COMPANION_APP_LIBRARY;
|
||||||
lastStatsRefresh = 0;
|
lastStatsRefresh = 0;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
|
|
||||||
@ -369,36 +369,20 @@ void CrossPointWebServerActivity::loop() {
|
|||||||
lastHandleClientTime = millis();
|
lastHandleClientTime = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle screen switching with arrow buttons
|
// Handle screen switching with front arrow buttons (Left or Right cycles forward)
|
||||||
if (mappedInput.wasPressed(MappedInputManager::Button::PageForward)) {
|
// Order: COMPANION_APP_LIBRARY -> WEB_BROWSER -> COMPANION_APP -> back to COMPANION_APP_LIBRARY
|
||||||
// Cycle to next screen: WEB_BROWSER -> COMPANION_APP -> COMPANION_APP_LIBRARY -> WEB_BROWSER
|
if (mappedInput.wasPressed(MappedInputManager::Button::Left) ||
|
||||||
|
mappedInput.wasPressed(MappedInputManager::Button::Right)) {
|
||||||
switch (currentScreen) {
|
switch (currentScreen) {
|
||||||
|
case FileTransferScreen::COMPANION_APP_LIBRARY:
|
||||||
|
currentScreen = FileTransferScreen::WEB_BROWSER;
|
||||||
|
break;
|
||||||
case FileTransferScreen::WEB_BROWSER:
|
case FileTransferScreen::WEB_BROWSER:
|
||||||
currentScreen = FileTransferScreen::COMPANION_APP;
|
currentScreen = FileTransferScreen::COMPANION_APP;
|
||||||
break;
|
break;
|
||||||
case FileTransferScreen::COMPANION_APP:
|
case FileTransferScreen::COMPANION_APP:
|
||||||
currentScreen = FileTransferScreen::COMPANION_APP_LIBRARY;
|
currentScreen = FileTransferScreen::COMPANION_APP_LIBRARY;
|
||||||
break;
|
break;
|
||||||
case FileTransferScreen::COMPANION_APP_LIBRARY:
|
|
||||||
currentScreen = FileTransferScreen::WEB_BROWSER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
updateRequired = true;
|
|
||||||
Serial.printf("[%lu] [WEBACT] Switched to screen: %d\n", millis(), static_cast<int>(currentScreen));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mappedInput.wasPressed(MappedInputManager::Button::PageBack)) {
|
|
||||||
// Cycle to previous screen: WEB_BROWSER -> COMPANION_APP_LIBRARY -> COMPANION_APP -> WEB_BROWSER
|
|
||||||
switch (currentScreen) {
|
|
||||||
case FileTransferScreen::WEB_BROWSER:
|
|
||||||
currentScreen = FileTransferScreen::COMPANION_APP_LIBRARY;
|
|
||||||
break;
|
|
||||||
case FileTransferScreen::COMPANION_APP:
|
|
||||||
currentScreen = FileTransferScreen::WEB_BROWSER;
|
|
||||||
break;
|
|
||||||
case FileTransferScreen::COMPANION_APP_LIBRARY:
|
|
||||||
currentScreen = FileTransferScreen::COMPANION_APP;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
Serial.printf("[%lu] [WEBACT] Switched to screen: %d\n", millis(), static_cast<int>(currentScreen));
|
Serial.printf("[%lu] [WEBACT] Switched to screen: %d\n", millis(), static_cast<int>(currentScreen));
|
||||||
@ -446,26 +430,23 @@ void CrossPointWebServerActivity::render() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawQRCode(const GfxRenderer& renderer, const int x, const int y, const std::string& data) {
|
// Draw QR code at specified position with configurable pixel size per module
|
||||||
// Implementation of QR code calculation
|
// Returns the size of the QR code in pixels (width = height = size * pixelsPerModule)
|
||||||
// The structure to manage the QR code
|
int drawQRCode(const GfxRenderer& renderer, const int x, const int y, const std::string& data,
|
||||||
|
const uint8_t pixelsPerModule = 7) {
|
||||||
QRCode qrcode;
|
QRCode qrcode;
|
||||||
uint8_t qrcodeBytes[qrcode_getBufferSize(4)];
|
uint8_t qrcodeBytes[qrcode_getBufferSize(4)];
|
||||||
Serial.printf("[%lu] [WEBACT] QR Code (%lu): %s\n", millis(), data.length(), data.c_str());
|
Serial.printf("[%lu] [WEBACT] QR Code (%lu): %s\n", millis(), data.length(), data.c_str());
|
||||||
|
|
||||||
qrcode_initText(&qrcode, qrcodeBytes, 4, ECC_LOW, data.c_str());
|
qrcode_initText(&qrcode, qrcodeBytes, 4, ECC_LOW, data.c_str());
|
||||||
const uint8_t px = 6; // pixels per module
|
|
||||||
for (uint8_t cy = 0; cy < qrcode.size; cy++) {
|
for (uint8_t cy = 0; cy < qrcode.size; cy++) {
|
||||||
for (uint8_t cx = 0; cx < qrcode.size; cx++) {
|
for (uint8_t cx = 0; cx < qrcode.size; cx++) {
|
||||||
if (qrcode_getModule(&qrcode, cx, cy)) {
|
if (qrcode_getModule(&qrcode, cx, cy)) {
|
||||||
// Serial.print("**");
|
renderer.fillRect(x + pixelsPerModule * cx, y + pixelsPerModule * cy, pixelsPerModule, pixelsPerModule, true);
|
||||||
renderer.fillRect(x + px * cx, y + px * cy, px, px, true);
|
|
||||||
} else {
|
|
||||||
// Serial.print(" ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Serial.print("\n");
|
|
||||||
}
|
}
|
||||||
|
return qrcode.size * pixelsPerModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to format bytes into human-readable sizes
|
// Helper to format bytes into human-readable sizes
|
||||||
@ -521,6 +502,10 @@ std::string CrossPointWebServerActivity::getCompanionAppLibraryUrl() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CrossPointWebServerActivity::renderServerRunning() const {
|
void CrossPointWebServerActivity::renderServerRunning() const {
|
||||||
|
// Switch to landscape orientation for the QR code screens (800x480)
|
||||||
|
const auto originalOrientation = renderer.getOrientation();
|
||||||
|
renderer.setOrientation(GfxRenderer::Orientation::LandscapeCounterClockwise);
|
||||||
|
|
||||||
// Dispatch to the appropriate screen
|
// Dispatch to the appropriate screen
|
||||||
switch (currentScreen) {
|
switch (currentScreen) {
|
||||||
case FileTransferScreen::WEB_BROWSER:
|
case FileTransferScreen::WEB_BROWSER:
|
||||||
@ -537,16 +522,20 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
|||||||
// Render stats bar at the bottom (above button hints)
|
// Render stats bar at the bottom (above button hints)
|
||||||
renderStats();
|
renderStats();
|
||||||
|
|
||||||
// Draw button hints with arrow navigation
|
// Restore orientation before drawing button hints (they handle their own orientation internally)
|
||||||
const auto labels = mappedInput.mapLabels("« Exit", "", "«", "»");
|
renderer.setOrientation(originalOrientation);
|
||||||
|
|
||||||
|
// Draw button hints - Left/Right cycle screens, Back exits
|
||||||
|
const auto labels = mappedInput.mapLabels("« Exit", "", "", "Next »");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrossPointWebServerActivity::renderStats() const {
|
void CrossPointWebServerActivity::renderStats() const {
|
||||||
if (!webServer) return;
|
if (!webServer) return;
|
||||||
|
|
||||||
const int screenHeight = renderer.getScreenHeight();
|
// In landscape (800x480), position stats near bottom but above button area
|
||||||
const int statsY = screenHeight - 70; // Position above button hints
|
const int screenHeight = renderer.getScreenHeight(); // 480 in landscape
|
||||||
|
const int statsY = screenHeight - 30;
|
||||||
|
|
||||||
// Get stats from web server
|
// Get stats from web server
|
||||||
const unsigned long uptime = webServer->getServerUptime();
|
const unsigned long uptime = webServer->getServerUptime();
|
||||||
@ -566,144 +555,169 @@ void CrossPointWebServerActivity::renderStats() const {
|
|||||||
statsLine += " (" + std::to_string(filesDown) + ")";
|
statsLine += " (" + std::to_string(filesDown) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, statsY, statsLine.c_str());
|
renderer.drawCenteredText(UI_10_FONT_ID, statsY, statsLine.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrossPointWebServerActivity::renderWebBrowserScreen() const {
|
void CrossPointWebServerActivity::renderWebBrowserScreen() const {
|
||||||
constexpr int LINE_SPACING = 28;
|
// Landscape layout (800x480): QR on left, text on right
|
||||||
|
constexpr int QR_X = 15;
|
||||||
|
constexpr int QR_Y = 15;
|
||||||
|
constexpr int QR_PX = 7; // pixels per QR module
|
||||||
|
constexpr int QR_SIZE = 33 * QR_PX; // QR version 4 = 33 modules = 231px
|
||||||
|
constexpr int TEXT_X = QR_X + QR_SIZE + 35; // Text starts after QR + margin
|
||||||
|
constexpr int LINE_SPACING = 32;
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer - Web Browser", true, EpdFontFamily::BOLD);
|
// Draw title on right side
|
||||||
|
renderer.drawText(NOTOSANS_14_FONT_ID, TEXT_X, QR_Y, "File Transfer - Web Browser", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
|
int textY = QR_Y + LINE_SPACING + 10;
|
||||||
|
|
||||||
if (isApMode) {
|
if (isApMode) {
|
||||||
// AP mode display - center the content block
|
// AP mode: Show WiFi QR code on left, connection info on right
|
||||||
int startY = 55;
|
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY, "Hotspot Mode", true, EpdFontFamily::BOLD);
|
|
||||||
|
|
||||||
std::string ssidInfo = "Network: " + connectedSSID;
|
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING, ssidInfo.c_str());
|
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 2, "Connect your device to this WiFi network");
|
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3,
|
|
||||||
"or scan QR code with your phone to connect to Wifi.");
|
|
||||||
// Show QR code for WiFi config
|
|
||||||
const std::string wifiConfig = std::string("WIFI:S:") + connectedSSID + ";;";
|
const std::string wifiConfig = std::string("WIFI:S:") + connectedSSID + ";;";
|
||||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, wifiConfig);
|
drawQRCode(renderer, QR_X, QR_Y, wifiConfig, QR_PX);
|
||||||
|
|
||||||
startY += 6 * 29 + 3 * LINE_SPACING;
|
|
||||||
// Show primary URL (hostname)
|
|
||||||
std::string hostnameUrl = std::string("http://") + AP_HOSTNAME + ".local/";
|
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, EpdFontFamily::BOLD);
|
|
||||||
|
|
||||||
// Show IP address as fallback
|
|
||||||
std::string ipUrl = "or http://" + connectedIP + "/";
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, ipUrl.c_str());
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "Open this URL in your browser");
|
|
||||||
|
|
||||||
// Show QR code for URL
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 6, "or scan QR code with your phone:");
|
|
||||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 7, hostnameUrl);
|
|
||||||
} else {
|
|
||||||
// STA mode display
|
|
||||||
const int startY = 55;
|
|
||||||
|
|
||||||
std::string ssidInfo = "Network: " + connectedSSID;
|
std::string ssidInfo = "Network: " + connectedSSID;
|
||||||
if (ssidInfo.length() > 28) {
|
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str());
|
||||||
ssidInfo.replace(25, ssidInfo.length() - 25, "...");
|
textY += LINE_SPACING;
|
||||||
|
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Scan QR code to connect to WiFi,");
|
||||||
|
textY += LINE_SPACING - 4;
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "then open the URL in your browser.");
|
||||||
|
textY += LINE_SPACING + 8;
|
||||||
|
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Browser URL:", true, EpdFontFamily::BOLD);
|
||||||
|
textY += LINE_SPACING - 4;
|
||||||
|
|
||||||
|
std::string webUrl = "http://" + connectedIP + "/";
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, webUrl.c_str(), true, EpdFontFamily::BOLD);
|
||||||
|
textY += LINE_SPACING - 4;
|
||||||
|
|
||||||
|
std::string hostnameUrl = std::string("or http://") + AP_HOSTNAME + ".local/";
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, hostnameUrl.c_str());
|
||||||
|
} else {
|
||||||
|
// STA mode: Show URL QR code on left, connection info on right
|
||||||
|
std::string webUrl = "http://" + connectedIP + "/";
|
||||||
|
drawQRCode(renderer, QR_X, QR_Y, webUrl, QR_PX);
|
||||||
|
|
||||||
|
std::string ssidInfo = "Network: " + connectedSSID;
|
||||||
|
if (ssidInfo.length() > 35) {
|
||||||
|
ssidInfo = ssidInfo.substr(0, 32) + "...";
|
||||||
}
|
}
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY, ssidInfo.c_str());
|
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str());
|
||||||
|
textY += LINE_SPACING;
|
||||||
|
|
||||||
std::string ipInfo = "IP Address: " + connectedIP;
|
std::string ipInfo = "IP Address: " + connectedIP;
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING, ipInfo.c_str());
|
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ipInfo.c_str());
|
||||||
|
textY += LINE_SPACING + 8;
|
||||||
|
|
||||||
// Show web server URL prominently
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, webUrl.c_str(), true, EpdFontFamily::BOLD);
|
||||||
std::string webInfo = "http://" + connectedIP + "/";
|
textY += LINE_SPACING - 4;
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 2, webInfo.c_str(), true, EpdFontFamily::BOLD);
|
|
||||||
|
|
||||||
// Also show hostname URL
|
|
||||||
std::string hostnameUrl = std::string("or http://") + AP_HOSTNAME + ".local/";
|
std::string hostnameUrl = std::string("or http://") + AP_HOSTNAME + ".local/";
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str());
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, hostnameUrl.c_str());
|
||||||
|
textY += LINE_SPACING + 4;
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, "Open this URL in your browser");
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Open this URL in your browser");
|
||||||
|
textY += LINE_SPACING - 4;
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "or scan QR code with your phone:");
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "or scan QR code with your phone:");
|
||||||
|
|
||||||
// Show QR code for URL
|
|
||||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 6, webInfo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrossPointWebServerActivity::renderCompanionAppScreen() const {
|
void CrossPointWebServerActivity::renderCompanionAppScreen() const {
|
||||||
constexpr int LINE_SPACING = 28;
|
// Landscape layout (800x480): QR on left, text on right
|
||||||
|
constexpr int QR_X = 15;
|
||||||
|
constexpr int QR_Y = 15;
|
||||||
|
constexpr int QR_PX = 7; // pixels per QR module
|
||||||
|
constexpr int QR_SIZE = 33 * QR_PX; // QR version 4 = 33 modules = 231px
|
||||||
|
constexpr int TEXT_X = QR_X + QR_SIZE + 35; // Text starts after QR + margin
|
||||||
|
constexpr int LINE_SPACING = 32;
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer - Companion App", true, EpdFontFamily::BOLD);
|
// Draw title on right side
|
||||||
|
renderer.drawText(NOTOSANS_14_FONT_ID, TEXT_X, QR_Y, "Companion App - Files", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
const int startY = 55;
|
int textY = QR_Y + LINE_SPACING + 10;
|
||||||
|
|
||||||
// Show network info
|
// Show network info
|
||||||
std::string ssidInfo = "Network: " + connectedSSID;
|
std::string ssidInfo = "Network: " + connectedSSID;
|
||||||
if (ssidInfo.length() > 28) {
|
if (ssidInfo.length() > 35) {
|
||||||
ssidInfo.replace(25, ssidInfo.length() - 25, "...");
|
ssidInfo = ssidInfo.substr(0, 32) + "...";
|
||||||
}
|
}
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY, ssidInfo.c_str());
|
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str());
|
||||||
|
textY += LINE_SPACING;
|
||||||
|
|
||||||
|
// Show scan instructions
|
||||||
if (isApMode) {
|
if (isApMode) {
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING,
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Connect to this WiFi first, then scan");
|
||||||
"Connect to this WiFi first, then scan QR code");
|
textY += LINE_SPACING - 4;
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "QR code with the Companion app.");
|
||||||
} else {
|
} else {
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING, "Scan QR code with the CrossPoint Companion app");
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Scan the QR code with a phone that");
|
||||||
|
textY += LINE_SPACING - 4;
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "has the CrossPoint Companion app.");
|
||||||
}
|
}
|
||||||
|
textY += LINE_SPACING + 8;
|
||||||
|
|
||||||
// Show companion app URL prominently
|
// Show alternative browser access
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Alternative Browser Access:", true, EpdFontFamily::BOLD);
|
||||||
|
textY += LINE_SPACING - 4;
|
||||||
|
std::string webUrl = "http://" + connectedIP + "/files";
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, webUrl.c_str());
|
||||||
|
|
||||||
|
// Draw QR code on left
|
||||||
const std::string appUrl = getCompanionAppUrl();
|
const std::string appUrl = getCompanionAppUrl();
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 2, appUrl.c_str(), true, EpdFontFamily::BOLD);
|
drawQRCode(renderer, QR_X, QR_Y, appUrl, QR_PX);
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, "or scan QR code:");
|
// Show deep link URL below QR code
|
||||||
|
const int urlY = QR_Y + QR_SIZE + 10;
|
||||||
// Show QR code for app URL (centered)
|
renderer.drawText(UI_12_FONT_ID, QR_X, urlY, appUrl.c_str(), true, EpdFontFamily::BOLD);
|
||||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, appUrl);
|
|
||||||
|
|
||||||
// Show HTTP URL for reference (smaller)
|
|
||||||
const int refY = startY + LINE_SPACING * 4 + 6 * 33 + 15; // Below QR code
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, refY, "Opens to: Device file browser");
|
|
||||||
std::string webUrl = "http://" + connectedIP + "/";
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, refY + 20, webUrl.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrossPointWebServerActivity::renderCompanionAppLibraryScreen() const {
|
void CrossPointWebServerActivity::renderCompanionAppLibraryScreen() const {
|
||||||
constexpr int LINE_SPACING = 28;
|
// Landscape layout (800x480): QR on left, text on right
|
||||||
|
constexpr int QR_X = 15;
|
||||||
|
constexpr int QR_Y = 15;
|
||||||
|
constexpr int QR_PX = 7; // pixels per QR module
|
||||||
|
constexpr int QR_SIZE = 33 * QR_PX; // QR version 4 = 33 modules = 231px
|
||||||
|
constexpr int TEXT_X = QR_X + QR_SIZE + 35; // Text starts after QR + margin
|
||||||
|
constexpr int LINE_SPACING = 32;
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer - Library Link", true, EpdFontFamily::BOLD);
|
// Draw title on right side
|
||||||
|
renderer.drawText(NOTOSANS_14_FONT_ID, TEXT_X, QR_Y, "Companion App - Library", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
const int startY = 55;
|
int textY = QR_Y + LINE_SPACING + 10;
|
||||||
|
|
||||||
// Show network info
|
// Show network info
|
||||||
std::string ssidInfo = "Network: " + connectedSSID;
|
std::string ssidInfo = "Network: " + connectedSSID;
|
||||||
if (ssidInfo.length() > 28) {
|
if (ssidInfo.length() > 35) {
|
||||||
ssidInfo.replace(25, ssidInfo.length() - 25, "...");
|
ssidInfo = ssidInfo.substr(0, 32) + "...";
|
||||||
}
|
}
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY, ssidInfo.c_str());
|
renderer.drawText(NOTOSANS_12_FONT_ID, TEXT_X, textY, ssidInfo.c_str());
|
||||||
|
textY += LINE_SPACING;
|
||||||
|
|
||||||
|
// Show scan instructions
|
||||||
if (isApMode) {
|
if (isApMode) {
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING,
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Connect to this WiFi first, then scan");
|
||||||
"Connect to this WiFi first, then scan QR code");
|
textY += LINE_SPACING - 4;
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "QR code with the Companion app.");
|
||||||
} else {
|
} else {
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING, "Scan QR code with the CrossPoint Companion app");
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Scan the QR code with a phone that");
|
||||||
|
textY += LINE_SPACING - 4;
|
||||||
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "has the CrossPoint Companion app.");
|
||||||
}
|
}
|
||||||
|
textY += LINE_SPACING + 8;
|
||||||
|
|
||||||
// Show companion app URL prominently
|
// Show alternative browser access
|
||||||
const std::string appUrl = getCompanionAppLibraryUrl();
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, "Alternative Browser Access:", true, EpdFontFamily::BOLD);
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 2, appUrl.c_str(), true, EpdFontFamily::BOLD);
|
textY += LINE_SPACING - 4;
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, "or scan QR code:");
|
|
||||||
|
|
||||||
// Show QR code for app URL (centered)
|
|
||||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, appUrl);
|
|
||||||
|
|
||||||
// Show what this link opens to
|
|
||||||
const int refY = startY + LINE_SPACING * 4 + 6 * 33 + 15; // Below QR code
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, refY, "Opens to: Your local Library");
|
|
||||||
std::string webUrl = "http://" + connectedIP + "/";
|
std::string webUrl = "http://" + connectedIP + "/";
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, refY + 20, webUrl.c_str());
|
renderer.drawText(UI_12_FONT_ID, TEXT_X, textY, webUrl.c_str());
|
||||||
|
|
||||||
|
// Draw QR code on left
|
||||||
|
const std::string appUrl = getCompanionAppLibraryUrl();
|
||||||
|
drawQRCode(renderer, QR_X, QR_Y, appUrl, QR_PX);
|
||||||
|
|
||||||
|
// Show deep link URL below QR code
|
||||||
|
const int urlY = QR_Y + QR_SIZE + 10;
|
||||||
|
renderer.drawText(UI_12_FONT_ID, QR_X, urlY, appUrl.c_str(), true, EpdFontFamily::BOLD);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,11 +20,11 @@ enum class WebServerActivityState {
|
|||||||
SHUTTING_DOWN // Shutting down server and WiFi
|
SHUTTING_DOWN // Shutting down server and WiFi
|
||||||
};
|
};
|
||||||
|
|
||||||
// File transfer screen tabs
|
// File transfer screen tabs (cycle order: LIBRARY -> WEB_BROWSER -> FILES -> LIBRARY)
|
||||||
enum class FileTransferScreen {
|
enum class FileTransferScreen {
|
||||||
WEB_BROWSER, // Default screen with HTTP URL and QR code
|
WEB_BROWSER, // Screen with HTTP URL and QR code
|
||||||
COMPANION_APP, // Screen with crosspoint://files deep link URL and QR code
|
COMPANION_APP, // Screen with crosspoint://files deep link URL and QR code
|
||||||
COMPANION_APP_LIBRARY // Screen with crosspoint://library deep link URL and QR code
|
COMPANION_APP_LIBRARY // Default screen with crosspoint://library deep link URL and QR code
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,8 +58,8 @@ class CrossPointWebServerActivity final : public ActivityWithSubactivity {
|
|||||||
// Performance monitoring
|
// Performance monitoring
|
||||||
unsigned long lastHandleClientTime = 0;
|
unsigned long lastHandleClientTime = 0;
|
||||||
|
|
||||||
// Screen navigation
|
// Screen navigation - start on Companion App Library screen
|
||||||
FileTransferScreen currentScreen = FileTransferScreen::WEB_BROWSER;
|
FileTransferScreen currentScreen = FileTransferScreen::COMPANION_APP_LIBRARY;
|
||||||
unsigned long lastStatsRefresh = 0;
|
unsigned long lastStatsRefresh = 0;
|
||||||
|
|
||||||
static void taskTrampoline(void* param);
|
static void taskTrampoline(void* param);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user