# OPDS Server Reordering ## Task Add the ability to reorder OPDS servers via a `sortOrder` field, editable on-device and with up/down buttons in the web UI. ## Changes Made ### Data Model (`src/OpdsServerStore.h`) - Added `int sortOrder = 0` field to `OpdsServer` struct ### Store Logic (`src/OpdsServerStore.cpp`) - `saveToFile()`: persists `sort_order` to JSON - `loadFromFile()`: reads `sort_order`, assigns sequential defaults to servers missing it, sorts after load - `migrateFromSettings()`: assigns `sortOrder = 1` to migrated server - `addServer()`: auto-assigns `sortOrder = max(existing) + 1` when left at 0 - `updateServer()`: re-sorts after update - Added `sortServers()` private helper: sorts by sortOrder ascending, ties broken case-insensitively by name (falling back to URL) - Added `moveServer(index, direction)`: swaps sortOrder with adjacent server, re-sorts, saves ### On-Device UI (`src/activities/settings/OpdsSettingsActivity.cpp`) - Added "Position" as first menu item (index 0), shifting all others by 1 - Uses `NumericStepperActivity` (new) for position editing: numeric stepper with Up/Down and PageForward/PageBack to increment/decrement - `saveServer()` now re-locates the server by name+url after sort to keep `serverIndex` valid ### NumericStepperActivity (new: `src/activities/util/NumericStepperActivity.{h,cpp}`) - Reusable numeric stepper modeled after `SetTimezoneOffsetActivity` - Displays value with highlight rect and up/down arrow indicators - Up/PageForward increment, Down/PageBack decrement (clamped to min/max) - Confirm saves, Back cancels - Side button hints show +/- ### Web API (`src/network/CrossPointWebServer.{h,cpp}`) - `GET /api/opds`: now includes `sortOrder` in response - `POST /api/opds`: preserves `downloadPath` and `sortOrder` on update - New `POST /api/opds/reorder`: accepts `{index, direction: "up"|"down"}`, calls `moveServer()` ### Web UI (`src/network/html/SettingsPage.html`) - Added up/down arrow buttons to each OPDS server card (hidden at boundaries) - Added `reorderOpdsServer()` JS function calling the new API endpoint ### i18n - Added `STR_POSITION` to all 9 translation YAML files - Regenerated `I18nKeys.h`, `I18nStrings.h`, `I18nStrings.cpp` ## Follow-up Items - None identified; build passes cleanly.