Add search, thumbnails, continue watching, playback speed, PWA install, sort, notes, and mark-watched
Eight usability additions on top of the mobile redesign: course cover-image thumbnails, a debounced library search, a Continue Watching section split from Recently Viewed, per-lesson playback speed control, an installable PWA manifest/icons, name sort in the library browser, per-lesson notes, and a bulk mark-course-as-watched action. Also fixes two real bugs found along the way: lesson_view.html was missing the viewport meta tag (so lesson pages weren't actually mobile-responsive), and update_lesson_progress always overwrote the whole progress entry, which would have silently deleted a saved note on the next routine autosave. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -123,6 +123,46 @@ built locally from a private Gitea repo rather than pulling the upstream image.
|
||||
it). If you rename your *currently loaded* course's folder, the app resets
|
||||
to the library view rather than serving a stale path.
|
||||
|
||||
## Eight usability features (this session)
|
||||
|
||||
Asked for after brainstorming what could make the app nicer to use — see
|
||||
`.claude/plans/dazzling-yawning-glacier.md` for the full scoping rationale.
|
||||
|
||||
1. **Course thumbnails** — `find_course_thumbnail()` looks for
|
||||
`cover`/`folder`/`thumbnail`/`thumb`/`poster` (`.jpg/.jpeg/.png/.webp`)
|
||||
directly inside a course folder; served via `GET /library/thumbnail`.
|
||||
Shown in the Library browser and Recently Viewed/Continue Watching,
|
||||
falling back to the emoji icon if there's no cover image.
|
||||
2. **Library search** — `GET /library/search?q=...` recursively walks the
|
||||
library (reusing `list_library_directory`'s hidden-path filtering) and
|
||||
matches on course name. Debounced search box above the Library browser.
|
||||
3. **Continue Watching** — reuses the Recently-Viewed history
|
||||
(`MAX_RECENT_VIEWS` bumped 5→20) rather than a full library-wide progress
|
||||
index; split into "in progress" vs. "recently touched" on the dashboard.
|
||||
4. **Playback speed control** — `settings.playback_speed` (0.75x–2x),
|
||||
persisted the same way video player size already was; speed buttons on
|
||||
the lesson page, applied on load via the existing `/api/settings` fetch.
|
||||
5. **Installable app (PWA)** — `static/manifest.json` +
|
||||
`static/icons/icon-{192,512}.png`, linked from every template's `<head>`.
|
||||
Install-only, deliberately **no service worker/offline caching** — this
|
||||
app has no real "offline" mode (it's a thin client over the Flask
|
||||
backend/NAS files), so a caching SW would just create stale-content bugs.
|
||||
Also fixed: `lesson_view.html` was missing the viewport meta tag entirely,
|
||||
so lesson/video pages weren't actually mobile-responsive until now.
|
||||
6. **Sort in the Library browser** — client-side Name A→Z/Z→A only;
|
||||
progress-based filtering (not-started/in-progress/done) was scoped out,
|
||||
since it'd need the same expensive per-course scan as #3's "ideal" version.
|
||||
7. **Per-lesson notes** — a `note` field alongside `completed`/
|
||||
`progress_seconds` in each lesson's existing progress-file entry, via
|
||||
`ProgressTracker.update_lesson_note()` / `POST /api/lesson-note`. Fixed a
|
||||
real bug in `update_lesson_progress` while at it: it always overwrote the
|
||||
entire lesson entry, which would have silently deleted a saved note on
|
||||
the next routine playback-progress autosave.
|
||||
8. **Mark course as watched** — `POST /api/course/mark-watched`, scoped to
|
||||
whatever course is currently loaded (not an arbitrary library path, to
|
||||
avoid re-validating/re-scanning an untrusted path). Button lives in the
|
||||
course stats card, behind a confirm prompt.
|
||||
|
||||
## Known limitations still open
|
||||
- App is unauthenticated by design (matches upstream) — settings and hidden-path
|
||||
curation apply app-wide, not per-browser/per-user.
|
||||
|
||||
Reference in New Issue
Block a user