fix: Wi-Fi Selection on Calibre Library launch

This commit is contained in:
danoooob 2026-01-10 22:38:15 +07:00
parent d4ae108d9b
commit 5160d16ea3
2 changed files with 51 additions and 36 deletions

View File

@ -7,7 +7,7 @@
#include "CrossPointSettings.h"
#include "MappedInputManager.h"
#include "ScreenComponents.h"
#include "WifiCredentialStore.h"
#include "activities/network/WifiSelectionActivity.h"
#include "fontIds.h"
#include "network/HttpDownloader.h"
#include "util/StringUtils.h"
@ -25,7 +25,7 @@ void OpdsBookBrowserActivity::taskTrampoline(void* param) {
}
void OpdsBookBrowserActivity::onEnter() {
Activity::onEnter();
ActivityWithSubactivity::onEnter();
renderingMutex = xSemaphoreCreateMutex();
state = BrowserState::CHECK_WIFI;
@ -49,7 +49,7 @@ void OpdsBookBrowserActivity::onEnter() {
}
void OpdsBookBrowserActivity::onExit() {
Activity::onExit();
ActivityWithSubactivity::onExit();
// Turn off WiFi when exiting
WiFi.mode(WIFI_OFF);
@ -66,13 +66,28 @@ void OpdsBookBrowserActivity::onExit() {
}
void OpdsBookBrowserActivity::loop() {
// Handle WiFi selection subactivity
if (state == BrowserState::WIFI_SELECTION) {
ActivityWithSubactivity::loop();
return;
}
// Handle error state - Confirm retries, Back goes back or home
if (state == BrowserState::ERROR) {
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
// Check if WiFi is still connected
if (WiFi.status() == WL_CONNECTED && WiFi.localIP() != IPAddress(0, 0, 0, 0)) {
// WiFi connected - just retry fetching the feed
Serial.printf("[%lu] [OPDS] Retry: WiFi connected, retrying fetch\n", millis());
state = BrowserState::LOADING;
statusMessage = "Loading...";
updateRequired = true;
fetchFeed(currentPath);
} else {
// WiFi not connected - launch WiFi selection
Serial.printf("[%lu] [OPDS] Retry: WiFi not connected, launching selection\n", millis());
launchWifiSelection();
}
} else if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
navigateBack();
}
@ -350,8 +365,8 @@ void OpdsBookBrowserActivity::downloadBook(const OpdsEntry& book) {
}
void OpdsBookBrowserActivity::checkAndConnectWifi() {
// Already connected?
if (WiFi.status() == WL_CONNECTED) {
// Already connected? Verify connection is valid by checking IP
if (WiFi.status() == WL_CONNECTED && WiFi.localIP() != IPAddress(0, 0, 0, 0)) {
state = BrowserState::LOADING;
statusMessage = "Loading...";
updateRequired = true;
@ -359,38 +374,34 @@ void OpdsBookBrowserActivity::checkAndConnectWifi() {
return;
}
// Try to connect using saved credentials
statusMessage = "Connecting to WiFi...";
// Not connected - launch WiFi selection screen directly
launchWifiSelection();
}
void OpdsBookBrowserActivity::launchWifiSelection() {
state = BrowserState::WIFI_SELECTION;
updateRequired = true;
WIFI_STORE.loadFromFile();
const auto& credentials = WIFI_STORE.getCredentials();
if (credentials.empty()) {
state = BrowserState::ERROR;
errorMessage = "No WiFi credentials saved";
updateRequired = true;
return;
}
enterNewActivity(new WifiSelectionActivity(renderer, mappedInput, [this](const bool connected) {
onWifiSelectionComplete(connected);
}));
}
// Use the first saved credential
const auto& cred = credentials[0];
WiFi.mode(WIFI_STA);
WiFi.begin(cred.ssid.c_str(), cred.password.c_str());
void OpdsBookBrowserActivity::onWifiSelectionComplete(const bool connected) {
exitActivity();
// Wait for connection with timeout
constexpr int WIFI_TIMEOUT_MS = 10000;
const unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < WIFI_TIMEOUT_MS) {
vTaskDelay(100 / portTICK_PERIOD_MS);
}
if (WiFi.status() == WL_CONNECTED) {
Serial.printf("[%lu] [OPDS] WiFi connected: %s\n", millis(), WiFi.localIP().toString().c_str());
if (connected) {
Serial.printf("[%lu] [OPDS] WiFi connected via selection, fetching feed\n", millis());
state = BrowserState::LOADING;
statusMessage = "Loading...";
updateRequired = true;
fetchFeed(currentPath);
} else {
Serial.printf("[%lu] [OPDS] WiFi selection cancelled/failed\n", millis());
// Force disconnect to ensure clean state for next retry
// This prevents stale connection status from interfering
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
state = BrowserState::ERROR;
errorMessage = "WiFi connection failed";
updateRequired = true;

View File

@ -8,25 +8,27 @@
#include <string>
#include <vector>
#include "../Activity.h"
#include "../ActivityWithSubactivity.h"
/**
* Activity for browsing and downloading books from an OPDS server.
* Supports navigation through catalog hierarchy and downloading EPUBs.
* When WiFi connection fails, launches WiFi selection to let user connect.
*/
class OpdsBookBrowserActivity final : public Activity {
class OpdsBookBrowserActivity final : public ActivityWithSubactivity {
public:
enum class BrowserState {
CHECK_WIFI, // Checking WiFi connection
LOADING, // Fetching OPDS feed
BROWSING, // Displaying entries (navigation or books)
DOWNLOADING, // Downloading selected EPUB
ERROR // Error state with message
CHECK_WIFI, // Checking WiFi connection
WIFI_SELECTION, // WiFi selection subactivity is active
LOADING, // Fetching OPDS feed
BROWSING, // Displaying entries (navigation or books)
DOWNLOADING, // Downloading selected EPUB
ERROR // Error state with message
};
explicit OpdsBookBrowserActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
const std::function<void()>& onGoHome)
: Activity("OpdsBookBrowser", renderer, mappedInput), onGoHome(onGoHome) {}
: ActivityWithSubactivity("OpdsBookBrowser", renderer, mappedInput), onGoHome(onGoHome) {}
void onEnter() override;
void onExit() override;
@ -54,6 +56,8 @@ class OpdsBookBrowserActivity final : public Activity {
void render() const;
void checkAndConnectWifi();
void launchWifiSelection();
void onWifiSelectionComplete(bool connected);
void fetchFeed(const std::string& path);
void navigateToEntry(const OpdsEntry& entry);
void navigateBack();