#pragma once // ============================================================================= // WebReaderScreen.h - Minimal Web Reader ("Reader Mode") for T-Deck Pro // // A Lynx-like web page reader that fetches URLs over WiFi, strips HTML to // readable text, extracts links as numbered references, and paginates // content for the e-ink display with keyboard navigation. // // Requires WiFi capability - wrap includes with appropriate guards. // Shortcut key: B (Browser) from home screen. // // Network backends: // - WiFi (default): Uses ESP32 WiFi STA mode. Credentials saved to SD. // - 4G/PPP (future): When PPP is established via A7682E modem, the same // HTTPClient code works transparently over cellular. To enable this, // establish PPP before calling fetchPage() and the ESP networking // stack will route through the modem automatically. // // Modes: // WIFI_SETUP - Connect to a WiFi network (scan + password entry) // HOME - URL bar, bookmarks, history // FETCHING - Loading indicator while downloading // READING - Paginated text view with numbered [links] // LINK_SELECT - Pick a link by number to follow // ============================================================================= #include #include #include "variant.h" #include #include #include #include #include #include #include #ifdef HAS_4G_MODEM #include "ModemManager.h" #endif #include "Utf8CP437.h" #include "../NodePrefs.h" // Forward declarations class UITask; // ============================================================================ // PSRAM allocator for mbedTLS // // ESP32-S3 internal RAM has only ~30KB largest contiguous block after WiFi // init, but TLS handshake needs ~32-48KB for I/O buffers. Redirect mbedtls // allocations to PSRAM (which has plenty of contiguous space) so HTTPS works. // ============================================================================ static void* _webreader_psram_calloc(size_t num, size_t size) { void* ptr = heap_caps_calloc(num, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (!ptr) ptr = calloc(num, size); // Fallback to internal if PSRAM fails return ptr; } static void _webreader_psram_free(void* ptr) { free(ptr); // Works for both PSRAM and internal allocations } static bool _webreader_tls_psram_set = false; static void ensureTlsUsesPsram() { #if defined(MBEDTLS_PLATFORM_MEMORY) || defined(CONFIG_MBEDTLS_PLATFORM_MEMORY) if (!_webreader_tls_psram_set) { mbedtls_platform_set_calloc_free(_webreader_psram_calloc, _webreader_psram_free); _webreader_tls_psram_set = true; Serial.println("WebReader: mbedTLS allocator redirected to PSRAM"); } #else if (!_webreader_tls_psram_set) { Serial.println("WebReader: WARNING - mbedTLS PSRAM redirect not available"); _webreader_tls_psram_set = true; } #endif } // ============================================================================ // Configuration // ============================================================================ #define WEB_CACHE_DIR "/web" #define WEB_BOOKMARKS_FILE "/web/bookmarks.txt" #define WEB_HISTORY_FILE "/web/history.txt" // IRC configuration #define IRC_CONFIG_FILE "/web/irc.cfg" #define IRC_MAX_MESSAGES 64 // Circular buffer size #define IRC_MAX_MSG_LEN 200 // Max display length per message #define IRC_MAX_NICK_LEN 16 #define IRC_MAX_CHANNEL_LEN 64 #define IRC_MAX_HOST_LEN 128 #define IRC_LINE_BUF_SIZE 512 // Raw IRC protocol line buffer #define IRC_COMPOSE_MAX 180 // Max compose message length #define IRC_RECONNECT_MS 10000 // Auto-reconnect delay #define IRC_PING_TIMEOUT_MS 300000 // 5 min no data = connection dead struct IRCMessage { char nick[IRC_MAX_NICK_LEN]; char text[IRC_MAX_MSG_LEN]; bool isSystem; // true for join/part/server notices }; #define WEB_MAX_PAGE_SIZE 196608 // Max HTML download size (192KB) #define WEB_MAX_TEXT_SIZE 98304 // Max extracted text size (96KB) #define WEB_MAX_LINKS 512 // Max links per page #define WEB_MAX_URL_LEN 256 #define WEB_MAX_BOOKMARKS 20 #define WEB_MAX_HISTORY 30 #define WEB_MAX_SSIDS 10 #define WEB_WIFI_PASS_LEN 64 #define WEB_USER_AGENT "Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36" // ============================================================================ // Link structure - stores extracted hyperlinks // ============================================================================ struct WebLink { char url[WEB_MAX_URL_LEN]; char text[48]; // Display text for the link (truncated) }; // ============================================================================ // Form structures - stores parsed HTML forms for user interaction // ============================================================================ #define WEB_MAX_FORMS 4 #define WEB_MAX_FORM_FIELDS 16 #define WEB_MAX_FIELD_VALUE 128 struct WebFormField { char name[64]; // name= attribute char value[WEB_MAX_FIELD_VALUE]; // Current/default value char label[48]; // Display label (from