mod: Phase 1 - bring forward mod-exclusive files with ActivityManager migration

Brings ~55 mod-exclusive files to the upstream-based mod/master-resync branch:

Activities (migrated to new ActivityManager pattern):
- Clock/Time: SetTimeActivity, SetTimezoneOffsetActivity, NtpSyncActivity
- Dictionary: DictionaryDefinitionActivity, DictionarySuggestionsActivity,
  DictionaryWordSelectActivity, LookedUpWordsActivity
- Bookmark: EpubReaderBookmarkSelectionActivity
- Book management: BookManageMenuActivity, EndOfBookMenuActivity
- OPDS: OpdsServerListActivity, OpdsSettingsActivity
- Utility: DirectoryPickerActivity, NumericStepperActivity

Utilities (unchanged):
- BookManager, BookSettings, BookmarkStore, BootNtpSync
- Dictionary, LookupHistory, TimeSync, OpdsServerStore

Libraries: PlaceholderCover, TableData, ChapterXPathIndexer
Scripts: inject_mod_version, generate_book_icon, preview_placeholder_cover
Docs: KOReader sync XPath mapping

Migration changes:
- ActivityWithSubactivity -> Activity base class
- Callback constructors -> finish()/setResult() pattern
- enterNewActivity() -> startActivityForResult()
- Activity::RenderLock&& -> RenderLock&&

These files won't compile yet - they reference mod settings and I18n
strings that will be added in subsequent phases.

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-07 15:10:00 -05:00
parent 170cc25774
commit dfbc931c14
147 changed files with 112771 additions and 1 deletions

View File

@@ -0,0 +1,280 @@
# CI, Build, Release & Code Style
This document covers the CrossPoint Reader build system, CI pipeline, release process, code formatting rules, static analysis, and contribution guidelines.
## Build System
The project uses **PlatformIO** with the Arduino framework targeting the ESP32-C3.
### Build Environments
Defined in `platformio.ini`:
| Environment | Purpose | Version String |
|---|---|---|
| `default` | Local development builds | `1.0.0-dev` |
| `gh_release` | Official tagged releases | `1.0.0` |
| `gh_release_rc` | Release candidates | `1.0.0-rc+{7-char SHA}` |
### Build Command
```bash
# Development build
pio run
# Release build
pio run -e gh_release
# Release candidate build (requires CROSSPOINT_RC_HASH env var)
CROSSPOINT_RC_HASH=abc1234 pio run -e gh_release_rc
```
### Build Flags
All environments share a common set of flags (`[base]` section):
| Flag | Purpose |
|---|---|
| `-std=c++2a` | C++20 standard |
| `-DARDUINO_USB_MODE=1` | USB mode selection |
| `-DARDUINO_USB_CDC_ON_BOOT=1` | Enable USB CDC serial on boot |
| `-DMINIZ_NO_ZLIB_COMPATIBLE_NAMES=1` | Avoid miniz/zlib symbol conflicts |
| `-DEINK_DISPLAY_SINGLE_BUFFER_MODE=1` | Single frame buffer (saves RAM) |
| `-DDISABLE_FS_H_WARNING=1` | Suppress Arduino FS.h warning |
| `-DXML_GE=0` | Disable expat general entity expansion |
| `-DXML_CONTEXT_BYTES=1024` | Expat context buffer size |
| `-DUSE_UTF8_LONG_NAMES=1` | Enable UTF-8 long filenames in SdFat |
### Pre-Build Step
`scripts/build_html.py` runs before compilation (configured via `extra_scripts = pre:scripts/build_html.py`). It:
1. Finds all `.html` files under `src/`.
2. Minifies them (strips comments, collapses whitespace, preserves `<pre>`, `<code>`, `<textarea>`, `<script>`, `<style>` blocks).
3. Generates `.generated.h` files containing `constexpr char ...Html[] PROGMEM = R"rawliteral(...)rawliteral";` strings.
### Dependencies
**SDK libraries** (symlinked from `open-x4-sdk` submodule):
- `BatteryMonitor`
- `InputManager`
- `EInkDisplay`
- `SDCardManager`
**External libraries** (managed by PlatformIO):
- `bblanchon/ArduinoJson @ 7.4.2` -- JSON parsing
- `ricmoo/QRCode @ 0.0.1` -- QR code generation
- `links2004/WebSockets @ 2.7.3` -- WebSocket server
### Tool Versions
| Tool | Version | Notes |
|---|---|---|
| PlatformIO | Latest (via pip) | `espressif32 @ 6.12.0` platform |
| Python | 3.14 | Used in CI and build scripts |
| clang-format | 21 | From LLVM apt repository |
| cppcheck | Latest (via PlatformIO) | Static analysis |
## CI Pipeline
All CI workflows are in `.github/workflows/`.
### `ci.yml` -- Main CI
**Triggers:** Push to `master`, all pull requests.
Runs **4 jobs in parallel** (the first 3 are independent; the 4th aggregates results):
#### 1. `clang-format` -- Code Formatting Check
1. Installs `clang-format-21` from the LLVM apt repository.
2. Runs `bin/clang-format-fix` on the full codebase.
3. Checks `git diff --exit-code` -- fails if any file was reformatted.
#### 2. `cppcheck` -- Static Analysis
1. Installs PlatformIO.
2. Runs `pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high`.
3. Fails on any low, medium, or high severity defect.
#### 3. `build` -- Compilation
1. Installs PlatformIO.
2. Runs `pio run` (default environment).
3. Extracts RAM and Flash usage stats into the GitHub step summary.
4. Uploads `firmware.bin` as a build artifact.
#### 4. `test-status` -- PR Gate
- Depends on all three jobs above.
- Fails if any dependency failed or was cancelled.
- This is the required status check for pull requests, decoupling CI steps from PR merge requirements.
### `pr-formatting-check.yml` -- PR Title Validation
**Triggers:** Pull request `opened`, `reopened`, `edited` events.
Uses `amannn/action-semantic-pull-request@v6` to enforce semantic PR title format (e.g., `feat: add dark mode`, `fix: correct page numbering`).
### `release.yml` -- Official Release
**Trigger:** Push of any git tag.
1. Builds using the `gh_release` environment.
2. Uploads release artifacts named `CrossPoint-{tag}`:
- `bootloader.bin`
- `firmware.bin`
- `firmware.elf`
- `firmware.map`
- `partitions.bin`
### `release_candidate.yml` -- RC Build
**Trigger:** Manual `workflow_dispatch`, restricted to branches matching `release/*`.
1. Extracts the 7-character short SHA and branch suffix (e.g., `v1.0.0` from `release/v1.0.0`).
2. Sets `CROSSPOINT_RC_HASH` env var.
3. Builds using the `gh_release_rc` environment.
4. Uploads artifacts named `CrossPoint-RC-{suffix}`.
## Release Process
### Official Release
1. Create and push a git tag (e.g., `v1.0.0`).
2. The `release.yml` workflow triggers automatically.
3. Artifacts are uploaded to the GitHub Actions run.
### Release Candidate
1. Create a branch named `release/{identifier}` (e.g., `release/v1.0.0`).
2. Navigate to Actions in GitHub and manually trigger `Compile Release Candidate` on that branch.
3. The RC version string includes the commit SHA for traceability.
### Version Scheme
```
1.0.0-dev # Local development (default env)
1.0.0 # Official release (gh_release env)
1.0.0-rc+a1b2c3d # Release candidate (gh_release_rc env)
```
The version base is set in `platformio.ini` under `[crosspoint] version = 1.0.0`.
## Code Style
### Formatting: clang-format
The project uses **clang-format 21** with a `.clang-format` config at the repository root. Key rules:
| Setting | Value | Meaning |
|---|---|---|
| `IndentWidth` | `2` | 2-space indentation |
| `TabWidth` / `UseTab` | `8` / `Never` | Spaces only (no tabs) |
| `ColumnLimit` | `120` | Maximum line width |
| `BreakBeforeBraces` | `Attach` | K&R brace style (opening brace on same line) |
| `PointerAlignment` | `Left` | `int* ptr` not `int *ptr` |
| `ReferenceAlignment` | `Pointer` | References follow pointer style |
| `ContinuationIndentWidth` | `4` | 4-space continuation indent |
| `AllowShortFunctionsOnASingleLine` | `All` | Short functions may be single-line |
| `AllowShortIfStatementsOnASingleLine` | `WithoutElse` | `if (x) return;` allowed |
| `AllowShortLoopsOnASingleLine` | `true` | Short loops may be single-line |
| `BreakBeforeTernaryOperators` | `true` | `?` and `:` start new lines |
| `BreakBeforeBinaryOperators` | `None` | Binary operators stay at end of line |
| `SortIncludes` | `Enabled` | Includes sorted lexicographically |
| `IncludeBlocks` | `Regroup` | Includes grouped by category |
| `ReflowComments` | `Always` | Long comments are rewrapped |
| `SpacesBeforeTrailingComments` | `2` | Two spaces before `// comment` |
| `LineEnding` | `DeriveLF` | Unix-style line endings |
### Include Order
Includes are regrouped into priority categories:
1. **Priority 1:** System headers with `.h` extension (`<foo.h>`)
2. **Priority 2:** Other system headers (`<foo>`) and extension headers (`<ext/foo.h>`)
3. **Priority 3:** Project-local headers (`"foo.h"`)
### Running the Formatter
```bash
# Format all tracked source files
./bin/clang-format-fix
# Format only modified (staged or unstaged) files
./bin/clang-format-fix -g
```
The script formats `.c`, `.cpp`, `.h`, `.hpp` files tracked by git, **excluding** `lib/EpdFont/builtinFonts/` (script-generated font headers).
### Static Analysis: cppcheck
Configuration in `platformio.ini`:
```
check_tool = cppcheck
check_flags = --enable=all
--suppress=missingIncludeSystem
--suppress=unusedFunction
--suppress=unmatchedSuppression
--suppress=*:*/.pio/*
--inline-suppr
```
- `--enable=all` enables all checks.
- Suppressed: missing system includes, unused functions (common in library code), PlatformIO build directory.
- `--inline-suppr` allows `// cppcheck-suppress` comments in source.
- CI fails on **any** defect severity (low, medium, or high).
Run locally:
```bash
pio check
```
## Contribution Guidelines
### PR Requirements
1. **Semantic PR title** -- enforced by CI. Must follow conventional format:
- `feat: ...`, `fix: ...`, `refactor: ...`, `docs: ...`, `chore: ...`, etc.
2. **PR template** (`.github/PULL_REQUEST_TEMPLATE.md`) must be filled out:
- **Summary:** Goal and changes included.
- **Additional Context:** Performance implications, risks, focus areas.
- **AI Usage:** Transparent disclosure -- `YES`, `PARTIALLY`, or `NO`.
3. **Code formatting** -- run `bin/clang-format-fix` before pushing. CI will reject unformatted code.
4. **Static analysis** -- ensure `pio check` passes without low/medium/high defects.
5. **Build** -- confirm `pio run` compiles without errors.
### Project Scope
All contributions must align with the project's core mission: **focused reading on the Xteink X4**. See `SCOPE.md` for full details.
**In scope:** UX improvements, document rendering (EPUB), typography, e-ink driver refinement, library management, local file transfer, language support.
**Out of scope:** Interactive apps, active connectivity (RSS/news/browsers), media playback, complex reader features (highlighting, notes, dictionary).
When unsure, open a Discussion before coding.
### Governance
From `GOVERNANCE.md`:
- **Assume good intent** in technical discussions.
- **Critique code, not people.**
- **Public by default** -- decisions happen in Issues, PRs, and Discussions.
- Maintainers guide technical direction for ESP32-C3 hardware constraints.
- Report harassment privately to `@daveallie`.
### Checklist Before Submitting
- [ ] Code compiles: `pio run`
- [ ] Code is formatted: `bin/clang-format-fix`
- [ ] Static analysis passes: `pio check`
- [ ] PR title follows semantic format
- [ ] PR template filled out (summary, context, AI disclosure)
- [ ] Changes align with project scope (`SCOPE.md`)