Commit Graph
36 Commits
Author SHA1 Message Date
jpirnay 2b1dbb6737 Add extended TiltModel 2026-05-11 16:29:40 +02:00
jpirnay fe60b12d86 Improving KOReader sync 2026-05-10 15:46:33 +02:00
jpirnay 82448e856e Merge pull request #179 from jpirnay/feat-pr1809
feat: Movable status bar and dual-edge progress bars (upstream PR 1809 by LSTAR1900)
2026-05-07 19:19:50 +02:00
jpirnay 4f140afd10 Movable status bar and dual-edge progress bars 2026-05-06 23:09:26 +02:00
jpirnay dedc5bd4af Send optional document metadata with KOSync progress uploads 2026-05-06 22:44:47 +02:00
jpirnayandCopilot 06dfc6c50b Recover parts of the regression fiasco
Co-authored-by: Copilot <copilot@github.com>
2026-05-02 18:19:23 +02:00
jpirnay 867bd34798 A couple of fixes 2026-04-30 12:08:30 +02:00
jpirnayandCopilot cefed0f6ce Yet another bionic reading implementation
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 09:11:49 +02:00
jpirnay aa9fae16d9 Integrate upstream #1392 by adriancaruana 2026-04-28 10:00:22 +02:00
jpirnayandCopilot 066ec3d56b Fixes
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 18:45:16 +02:00
jpirnayandCopilot aed297b2b1 First attempt
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 15:30:43 +02:00
jpirnayandCopilot 7533ed1a9c Add font foverrides to reader menu
Co-authored-by: Copilot <copilot@github.com>
2026-04-24 11:38:55 +02:00
Arthur TazhitdinovandCopilot c867669560 feat: Support for multiple OPDS servers (#1209)
* Add support for configuring and using multiple OPDS servers, replacing
the previous single-server limitation. Closes
https://github.com/crosspoint-reader/crosspoint-reader/issues/1178
* New OpdsServerStore singleton (modeled after WifiCredentialStore) that
persists up to 8 OPDS servers to /.crosspoint/opds.json with MAC-based
password obfuscation.
* One-time migration from legacy single-server fields in
CrossPointSettings to the new store on first boot.
* New OpdsServerListActivity for the device UI — works in two modes: a
settings list (add/edit/delete servers) and a picker (select which
server to browse). When only one server is configured, the picker is
skipped automatically.
* Renamed CalibreSettingsActivity → OpdsSettingsActivity for clarity. It
now edits individual OpdsServer entries (name, URL, username, password,
delete).
* OpdsBookBrowserActivity now receives an OpdsServer at construction and
uses its credentials for all fetches/downloads, and shows the server
name in the header.
* HttpDownloader::fetchUrl and downloadToFile accept optional per-call
username/password parameters instead of reading from global settings.
* REST API endpoints on CrossPointWebServer: GET /api/opds, POST
/api/opds, POST /api/opds/delete — passwords are never exposed over the
API (only a hasPassword flag), and omitting the password field on update
preserves the existing one.
* Web UI (SettingsPage.html) with dynamic OPDS server management cards —
add, edit, save, and delete servers from the browser.
<img width="932" height="906" alt="SCR-20260416-stvu"
src="https://github.com/user-attachments/assets/a8f18d84-4204-46a0-bb31-b73d24b3255f"
/>

* The OpdsServerStore JSON format and obfuscation scheme are identical
to WifiCredentialStore, so the same JsonSettingsIO infrastructure
handles both.
* The web API uses POST /api/opds/delete instead of DELETE /api/opds
because the ESP32 WebServer doesn't support the DELETE method with a
request body.
* Existing single-server configurations are migrated automatically — no
user action required. After migration the legacy CrossPointSettings
fields are cleared so it only runs once.
* The HttpDownloader changes are backward-compatible: the credential
parameters default to empty strings, so existing callers are unaffected.

---

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< YES >**_

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-23 11:14:50 +02:00
jpirnay 29284c85c9 Review comments 2026-04-20 13:28:56 +02:00
jpirnay 8b6db63788 Add guard 2026-04-17 16:33:15 +02:00
jpirnay e0fb3e0160 More comments 2026-04-17 16:25:29 +02:00
jpirnay a8816b2964 Remove outdated static variant 2026-04-17 16:16:27 +02:00
jpirnay 106e9d31e6 Reduce heap pressure 2026-04-17 15:53:57 +02:00
jpirnay 2f4cea3706 Add Global Bookmark feature 2026-04-15 09:32:52 +02:00
jpirnay 1c3ba11563 Attempt at closing reader and sync 2026-04-13 19:10:32 +02:00
jpirnay fb8196e946 Change index type 2026-04-07 11:12:07 +02:00
jpirnay cb7c019367 Merge branch 'chore-display-last-known-mac' of https://github.com/jpirnay/crosspoint-reader into mybuild 2026-04-01 11:49:08 +02:00
jpirnay 90861a0bc9 Review changes, use espfuse mac 2026-04-01 11:48:50 +02:00
jpirnay f8f6753e15 Merge branch 'chore-display-last-known-mac' of https://github.com/jpirnay/crosspoint-reader into mybuild 2026-04-01 11:28:41 +02:00
jpirnay 62fd82a5bf Remember and use last known mac address for immediate display 2026-04-01 11:28:20 +02:00
jpirnay 9cdc1b8784 Resync with PR 1534 2026-04-01 11:00:51 +02:00
jpirnay f764d9c6a0 Merge remote-tracking branch 'pablohc/refactor/pr-1258-cover-overlay' into mybuild
# Conflicts:
#	lib/I18n/translations/english.yaml
#	scripts/gen_i18n.py
#	src/CrossPointSettings.h
#	src/SettingsList.h
#	src/activities/boot_sleep/SleepActivity.cpp
#	src/activities/boot_sleep/SleepActivity.h
2026-03-30 16:12:00 +02:00
pablohc 0f1d3ef31d fix: localize sleep overlay strings, validate TXT cache header, migrate overlay enum 2026-03-29 21:55:51 +02:00
jpirnay b240ef1e21 Merge branch 'feat-localoverride' of https://github.com/jpirnay/crosspoint-reader into mybuild 2026-03-20 18:38:23 +01:00
jpirnay 09e65c30a3 Local overrides for css and img display 2026-03-20 18:17:34 +01:00
jpirnay 9b70ddc93b Merge branch 'master' of https://github.com/jpirnay/crosspoint-reader into mybuild 2026-03-13 21:24:04 +01:00
jpirnay fb3997aae5 fix: Init lastSleepImage (edge case) (#1360)
## Summary

* **What is the goal of this PR?** fix edge case for definition

## Additional Context

If loadFromFile() returns false (no state file exists — first boot, or
SD missing), lastSleepImage is never set and contains garbage.
[SleepActivity.cpp:83] then uses it in a while comparison to avoid
repeating the same image. The JSON path (doc["lastSleepImage"] |
(uint8_t)0) handles it, but only if the file exists.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _** NO **_
2026-03-11 18:37:13 -05:00
jpirnay 3ed96a7e49 Use and populate metadata 2026-03-07 18:02:21 +01:00
jpirnay ad0f1fd00a refactor: Simplify new setting introduction (#1086)
## Summary

* **What is the goal of this PR?** Eliminate the 3-file / 4-location
overhead for adding a new setting. Previously, every new setting
required manually editing JsonSettingsIO.cpp in two places (save +
load), duplicating knowledge already present in SettingsList.h. After
this PR, JsonSettingsIO.cpp never needs to be touched again for standard
settings.
* **What changes are included?**
* `SettingInfo` (in `SettingsActivity.h`) gains one new field: `bool
obfuscated` (base64 save/load for passwords), with a fluent builder
method `.withObfuscated()`. The previously proposed
`defaultValue`/`withDefault()` approach was dropped in favour of reading
the struct field's own initializer value as the fallback (see below).
* `SettingsList.h` entries are annotated with `.withObfuscated()` on the
OPDS password entry. The list is now returned as a `static const`
singleton (`const std::vector<SettingInfo>&`), so it is constructed
exactly once. A missing `key`/`category` on the
`statusBarProgressBarThickness` entry was also fixed — it was previously
skipped by the generic save loop, so changes were silently lost on
restart.
* `JsonSettingsIO::saveSettings` and `loadSettings` replace their ~90
lines of manual per-field code with a single generic loop over
`getSettingsList()`. The loop uses `info.key`,
`info.valuePtr`/`info.stringOffset`+`info.stringMaxLen` (for char-array
string fields), `info.enumValues.size()` (for enum clamping), and
`info.obfuscated`.
* **Default values**: instead of a duplicated `defaultValue` field in
`SettingInfo`, `loadSettings` reads `s.*(info.valuePtr)` *before*
overwriting it. Because `CrossPointSettings` is default-constructed
before `loadSettings` is called, this captures each field's struct
initializer value as the JSON-absent fallback. The single source of
truth for defaults is `CrossPointSettings.h`.
* One post-loop special case remains explicitly: the four `frontButton*`
remap fields (managed by the RemapFrontButtons sub-activity, not in
SettingsList) and `validateFrontButtonMapping()`.
* One pre-loop migration guard handles legacy settings files that
predate the status bar refactor: if `statusBarChapterPageCount` is
absent from the JSON, `applyLegacyStatusBarSettings()` is called first
so the generic loop picks up the migrated values as defaults and applies
its normal clamping.
* OPDS password backward-compat migration (plain `opdsPassword` →
obfuscated `opdsPassword_obf`) is preserved inside the generic
obfuscated-string path.

## Additional Context
Say we want to add a new `bookmarkStyle` enum setting with options
`DOT`, `LINE`, `NONE` and a default of `DOT`:

1. `src/CrossPointSettings.h` — add enum and member:
```cpp
enum BOOKMARK_STYLE { BOOKMARK_DOT = 0, BOOKMARK_LINE = 1, BOOKMARK_NONE = 2 };
uint8_t bookmarkStyle = BOOKMARK_DOT;
```

2. `lib/I18n/translations/english.yaml` — add display strings:
```yaml
STR_BOOKMARK_STYLE: "Bookmark Style"
STR_BOOKMARK_DOT: "Dot"
STR_BOOKMARK_LINE: "Line"
```
(Other language files will fall back to English if not translated. Run
`gen_i18n.py` to regenerate `I18nKeys.h`.)

3. `src/SettingsList.h` — add one entry in the appropriate category:
```cpp
SettingInfo::Enum(StrId::STR_BOOKMARK_STYLE, &CrossPointSettings::bookmarkStyle,
                  {StrId::STR_BOOKMARK_DOT, StrId::STR_BOOKMARK_LINE, StrId::STR_NONE_OPT},
                  "bookmarkStyle", StrId::STR_CAT_READER),
```

That's it — no default annotation needed anywhere, because
`bookmarkStyle = BOOKMARK_DOT` in the struct already provides the
fallback. The setting will automatically persist to JSON on save, load
with clamping on boot, appear in the device settings UI under the Reader
category, and be exposed via the web API — all with no further changes.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< PARTIALLY>**_
2026-03-01 12:54:58 +11:00
James WhyteandArthur Tazhitdinov 8af0173d5b feat: split status bar setting (#733)
## Summary

This PR aims to reduce the complexity of the status bar by splitting the
setting into 5:
- Chapter Page Count
- Book Progress %
- Progress Bar
- Chapter Title
- Battery Indicator

These are located within the new StausBarSettings activity, which also
shows a preview of the bar the user has created

<img width="513" height="806" alt="image"
src="https://github.com/user-attachments/assets/cdf852fb-15d8-4da2-a74f-fd69294d7b05"
/>


<img width="483" height="797" alt="image"
src="https://github.com/user-attachments/assets/66fc0c0d-ee51-4d31-b70d-e2bc043205d1"
/>


When updating from a previous version, the user's past settings are
honoured.

## Additional Context

The PR aims to remove any duplication of status bar code where possible,
and extracts the status bar rendering into a new component - StatusBar

It also adds a new (optional) padding option to the progress bar to
allow the status bar to be shifted upwards - this is only intended for
use in the settings.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code?
No - although did help to decode some C++ errors

---------

Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
2026-02-25 13:06:38 +03:00
jpirnayandDave Allie cd748a01a9 feat: Migrate binary settings to json (#920)
## Summary

* This PR introduces a migration from binary file storage to JSON-based
storage for application settings, state, and various credential stores.
This improves readability, maintainability, and allows for easier manual
configuration editing.
* Benefits:
  - Settings files are now JSON and can be easily read/edited manually
  - Easier to inspect application state and settings during development
  - JSON structure is more flexible for future changes
* Drawback: around 15k of additional flash usage
* Compatibility: Seamless migration preserves existing user data

## Additional Context
1. New JSON I/O Infrastructure files:
- JsonSettingsIO: Core JSON serialization/deserialization logic using
ArduinoJson library
- ObfuscationUtils: XOR-based password obfuscation for sensitive data
2. Migrated Components (now use JSON storage with automatic binary
migration):
     - CrossPointSettings (settings.json): Main application settings
- CrossPointState (state.json): Application state (open book, sleep
mode, etc.)
- WifiCredentialStore (wifi.json): WiFi network credentials (Password
Obfuscation: Sensitive data like WiFi passwords, uses XOR encryption
with fixed keys. Note: This is obfuscation, not cryptographic security -
passwords can be recovered with the key)
- KOReaderCredentialStore (koreader.json): KOReader sync credentials
     - RecentBooksStore (recent.json): Recently opened books list
3. Migration Logic
     - Forward Compatibility: New installations use JSON format
- Backward Compatibility: Existing binary files are automatically
migrated to JSON on first load
- Backup Safety: Original binary files are renamed with .bak extension
after successful migration
- Fallback Handling: If JSON parsing fails, system falls back to binary
loading
4. Infrastructure Updates
     - HalStorage: Added rename() method for backup operations

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _** YES**_

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
2026-02-22 17:18:25 +11:00