Course tree (lesson-page sidebar + dashboard's loaded-course view) and
File Management's Manage Library browser both move from boxed,
bordered rows to a flat list: no per-row background/border, a small
leading chevron that doubles as the expand affordance instead of a
separate right-edge button, indentation for hierarchy. The chevron's
rotation is pure CSS (:has(+ .tree-content.expanded) / :has(+
.curate-children.expanded)) rather than JS swapping glyph text, which
also let a fair amount of now-redundant JS come out.
The course tree's new styles are scoped under .tree-container (course
dashboard) and .lesson-sidebar (lesson page) so they don't leak into
the Library folder browser and other rows that reuse the same base
.tree-header/.lesson-item/etc. class names elsewhere in
course_dashboard.html - confirmed those are visually untouched.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
An "Expand all" link above the tree (toggling to "Collapse all" once
everything's open) opens or closes every section at once - on both
the lesson page's sidebar and the dashboard's loaded-course view.
Toggles stay right-aligned per section, matching convention rather
than moving to the left. Label reflects current state on load and
persists through the same remembered-sections mechanism as manual
expand/collapse.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Dashboard header shortened to match every other page (was notably
taller than the rest).
- Files moved before Settings in the bottom nav.
- Removed the header's course-name badge - purely redundant with the
page's own heading directly below it.
- Fixed a dead link: "Progress" pointed to #stats, but no element
with that id existed anywhere on the page.
- Added a visible :focus-visible ring across all pages - tabbing
through the site previously gave no indication of what was focused.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Course outline sidebar now sits on the left of the player instead
of the right (mobile stacking order unchanged - video still first).
- Collapsible to a slim rail via a toggle button, remembered per
device, for a full-width player when wanted.
- Which sections a user has manually expanded is now remembered
(keyed by the section's path) and shared between the lesson-page
sidebar and the dashboard's course view, so re-opening a course
doesn't reset everything back to collapsed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Section and lesson names in the course-outline sidebar/tree get
clipped with an ellipsis when they don't fit - a title attribute now
shows the full text on hover.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Shows every section and lesson in the course - videos and standalone
documents alike - so jumping to a different section no longer means
backing out to the course page first. Current lesson is highlighted,
its section auto-expands and scrolls into view; sticky on desktop,
stacks below the player on narrow viewports. Replaces the old
"Lessons in this section" list, which only showed the current
section.
The tree-rendering markup (shared with the loaded-course dashboard
view) is now a single macro in templates/_course_tree.html instead of
being duplicated, so both views stay in sync going forward.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Filename-similarity matching within a folder can't distinguish a real
re-download duplicate from a course that splits one topic across
several numbered files ("...Part 1"/"...Part 2", "-1"/"-2"/"-3") -
both look like near-100% matches by name alone, and the latter is a
common, completely normal pattern. This produced hundreds of false
positives in practice. Removes Duplicate Lesson Files entirely
(detection function, its two API routes, and the File Management UI
section); whole-course-folder matching (Duplicate Courses) is
unaffected and stays the only duplicate scan in the app.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Many course platforms (Pluralsight, Packt, ...) open with a generic
branded bumper animation running 10-20s before the actual course
title card. The 8s candidate window landed squarely inside that
bumper and grabbed the platform logo instead of anything
course-specific. Candidates now spread across the first ~25s.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Concurrent requests for the same course's thumbnail (e.g. the
Precompute background scan overlapping an ordinary page load) shared
fixed candidate filenames, so one request's cleanup could delete a
temp file the other was still using, crashing with ENOENT. Candidate
filenames are now unique per call.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Auto-play next lesson on end, with a cancelable countdown and a
Settings toggle (default on).
- Grid-view course cards show a small progress ring (checkmark at
100%) instead of a separate bar.
- Duplicate Lesson Files: scans within each course/folder for media
files that look like the same lesson downloaded twice, with per-file
delete and a shared ignore list with Duplicate Courses.
- Auto-generated cover art now samples a few early candidate frames
and keeps the largest JPEG, favoring an intro title card over a
blank fade-in or a plain presenter frame.
- Settings -> "Regenerate Thumbnails" re-runs that logic for every
course with an auto-generated thumbnail (never touches manual
covers), so already-cached thumbnails can pick up the improvement.
- Add .gitignore for __pycache__/.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Favorites: star toggle on course rows, the course page, and a new
dashboard card; rebased on rename/move, backed up/restored, and
caught by stale-reference cleanup (also fixed a pre-existing gap
where favorites.json wasn't in the backup file list).
- Storage Usage: click a folder row to drill into its contents one
level at a time, with a Back button.
- Lesson player: added ,/. (speed step), [/] (prev/next lesson), and
F (fullscreen) keyboard shortcuts.
- Settings: a CHANGELOG.md-backed "What's New" list, since VERSION
alone only ever shows the current build.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>