# Port Upstream PRs #1207 and #1209 ## Task Ported two upstream PRs from crosspoint-reader/crosspoint-reader to the fork: - **PR #1207**: `fix: use HTTPClient::writeToStream for downloading files from OPDS` - **PR #1209**: `feat: Support for multiple OPDS servers` Cherry-picking was not possible due to significant divergences (WiFiClient vs NetworkClient naming, i18n changes, binary vs JSON settings, missing JsonSettingsIO/ObfuscationUtils). ## Changes Made ### PR #1207 (2 files modified) - `src/network/HttpDownloader.cpp` — Added `FileWriteStream` class, replaced manual chunked download loop with `HTTPClient::writeToStream`, improved Content-Length handling and post-download validation - `src/activities/browser/OpdsBookBrowserActivity.cpp` — Truncated download status text to fit screen width ### PR #1209 (6 files created, ~15 files modified, 2 files deleted) **New files:** - `src/OpdsServerStore.h` / `src/OpdsServerStore.cpp` — Singleton store for up to 8 OPDS servers with MAC-based XOR+base64 password obfuscation and JSON persistence (self-contained — fork lacks JsonSettingsIO/ObfuscationUtils, so persistence was inlined) - `src/activities/settings/OpdsServerListActivity.h` / `.cpp` — Dual-mode activity: settings list (add/edit/delete) and server picker - `src/activities/settings/OpdsSettingsActivity.h` / `.cpp` — Individual server editor (name, URL, username, password, delete) **Modified files:** - `src/network/HttpDownloader.h` / `.cpp` — Added per-call username/password parameters (default empty), removed global SETTINGS dependency - `src/activities/browser/OpdsBookBrowserActivity.h` / `.cpp` — Constructor accepts `OpdsServer`, uses server-specific credentials and URL, shows server name in header - `src/activities/home/HomeActivity.h` / `.cpp` — `hasOpdsUrl` → `hasOpdsServers`, uses `OPDS_STORE.hasServers()` - `src/main.cpp` — Added OPDS_STORE loading on boot, server picker when multiple servers configured - `src/activities/settings/SettingsActivity.cpp` — Replaced CalibreSettingsActivity with OpdsServerListActivity - `src/network/CrossPointWebServer.h` / `.cpp` — Added REST endpoints: GET/POST /api/opds, POST /api/opds/delete - `src/network/html/SettingsPage.html` — Added OPDS server management UI (CSS + JS) - `src/SettingsList.h` — Removed legacy OPDS entries (opdsServerUrl, opdsUsername, opdsPassword) - 9 translation YAML files — Added STR_ADD_SERVER, STR_SERVER_NAME, STR_NO_SERVERS, STR_DELETE_SERVER, STR_DELETE_CONFIRM, STR_OPDS_SERVERS **Deleted files:** - `src/activities/settings/CalibreSettingsActivity.h` / `.cpp` ## Key Adaptation Decisions - Kept `WiFiClient`/`WiFiClientSecure` naming (fork hasn't adopted `NetworkClient` rename) - Inlined JSON persistence and MAC-based obfuscation directly into `OpdsServerStore.cpp` (fork lacks `JsonSettingsIO` and `ObfuscationUtils` libraries) - Legacy single-server settings auto-migrate to new `opds.json` on first boot ## Build Status Compilation verified: SUCCESS (RAM: 32.8%, Flash: 71.4%)