Commit Graph
30 Commits
Author SHA1 Message Date
rmsitzandClaude Sonnet 5 255361ca6e Make browser back button step up one Library folder instead of exiting
Drilling into a Library folder only ever swapped #library-groups's
contents via fetch, never touching browser history - so back had
nothing of the app's own to step through once you were a few folders
deep, and fell straight through to exiting the app instead of going up
a level.

Push a history entry per drill-down and breadcrumb jump, and restore
libraryTrail/re-fetch that level on popstate, so back now un-drills
one folder at a time and only reaches the app's actual exit once
you're back at the library root.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 20:55:44 -04:00
rmsitzandClaude Sonnet 5 68639a2b5b Fix chapter-name regex missing underscore-joined folder names
_SECTION_NAME_RE used \b after keywords like "chapter", but \b doesn't
fire between "Chapter" and an immediately-following "_" since
underscore counts as a word character too - so a course whose chapter
folders were named "Chapter_1-Introduction" (no space) failed to match
and got misclassified as a plain folder instead of a course.

Swap \b for a (?![a-z]) negative lookahead, which correctly rejects
only a following letter (e.g. "Chapterhouse") while accepting a digit,
underscore, hyphen, space, or end of string.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 20:41:11 -04:00
rmsitzandClaude Sonnet 5 21a468fb7f Fix course-detection heuristic swallowing category folders as one course
_looks_like_course() treated any folder with 2+ media-holding subfolders
as a single multi-section course, with no check that those subfolders
actually looked like sections. A category folder holding many unrelated
courses (e.g. Claude/, General/) could accidentally satisfy that if
several of its courses happened to keep episodes directly at their own
top level rather than nested under a chapter folder, collapsing the
whole category into one bogus course.

Now every media-holding subfolder must read as a chapter/section label
(Section 1, Module 2, or a numbered chapter like 01-Introduction) for
the parent to count as one course - verified against the real library
mount that ChatGPT/Claude/Copilot/General all correctly show as
folders again, while individually-structured courses still detect
correctly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 20:33:02 -04:00
rmsitzandClaude Sonnet 5 8b365c4463 Add timestamped notes: multi-note support, quick-capture hotkey, live saved indicator
Replace the single free-text note per lesson with a list of timestamped
note entries, migrated transparently from the old format. Adds a
floating notes panel on the lesson page with an always-reachable
quick-capture bar (press N to pause and jump in), inline edit/delete,
click-to-seek timestamps, and a live "Saved Xs ago" indicator. Notes
Hub, the study guide export, and the Outline push all updated to
render multiple timestamped notes per lesson.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 20:17:20 -04:00
rmsitzandClaude Sonnet 5 c871d6efae Visual polish: theme-aware colors, collapsible cards, skeletons, hover consistency
Templates only, no backend changes:

- Fixed the real bug: JS-generated status/loading text and a few component
  styles used hardcoded hex (#007acc, #999/#666, #28a745, #ff6b6b) instead
  of the CSS variables the theme system already provides, so they didn't
  track the user's chosen theme/accent - most visible on Light or any named
  theme other than the default. Added --success/--error to all 5 templates'
  :root blocks and replaced every non-:root occurrence. Left the
  .lesson-type badge colors and generic UI chrome grays alone (intentional,
  not theme-dependent). Verified live by switching to Nord and Light themes.
- Dashboard cards (Library Stats, Next Up, Pick Back Up, Recently Added,
  Continue Watching, Recently Viewed) are now collapsible, state remembered
  per device via localStorage - the no-course dashboard had grown to 7
  stacked cards.
- Course page's three action buttons get consistent compact sizing and
  icons instead of a plain stack.
- Library browser and transcript search show shimmering skeleton rows
  instead of bare "Loading..."/"Searching..." text while a fetch is in
  flight.
- Hover treatment made consistent: transcript results get the same lift
  .lesson-item already had, heatmap cells get a GitHub-style hover
  scale-up, and Notes Hub links get a background-chip hover.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 19:31:31 -04:00
rmsitzandClaude Sonnet 5 0454834e62 Add Notes Hub, transcript search, stale nudges, study guide export, Next Up queue, activity heatmap
Six more dashboard features, all built on the per-course progress-file
scanning infrastructure from earlier sessions:

- Notes Hub (/notes): every lesson note across the library in one place,
  newest first, reusing the existing /recent/open cross-course jump route.
- Transcript search: opt-in checkbox on the Library search box, searching
  inside .srt/.vtt files. Kept cheap by doing a raw substring match as the
  filter step and only extracting a snippet for files that actually match.
- Stale course nudges ("Pick Back Up"): courses with progress that haven't
  been touched in 14+ days.
- Study guide export: compiles a course's notes into one downloadable
  markdown file, section/lesson structure preserved.
- Next Up queue: an ordered, persisted "what to tackle next" list with
  up/down reordering and a queue button on every course row.
- Activity heatmap: a 90-day contribution-style calendar in the Library
  Stats card.

_scan_library_activity() now does one walk over every course's progress
file per dashboard load; library stats, stale courses, and the heatmap all
derive from that single scan instead of three independent ones.

Also refactored the duplicated lesson-progress-key lookup (used in three
places now) into _resolve_lesson_progress_key(), and flagged a pre-existing
bug found along the way (not fixed here, kept out of scope): subtitle files
never actually attach to a Lesson object, so the video player's caption
track has never had anything to render.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 19:04:01 -04:00
rmsitzandClaude Sonnet 5 145f91a647 Fix note-field space bar hijacking video, rework Outline topics as documents
- Lesson page's global keyboard shortcuts (space/arrows for play-pause/
  seek/volume) fired regardless of focus, so typing a space in the notes
  textarea toggled the video instead of typing. Now skipped entirely
  whenever a text field/select has focus.
- Outline topics no longer spawn their own top-level collection each time.
  A topic is now a document inside one fixed, user-configured collection
  (Settings -> Outline Integration -> Default collection), and a lesson's
  note becomes a child document nested under its topic - matching how
  notes actually get organized in a real Outline instance instead of
  cluttering the collections list with one per topic.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 12:27:00 -04:00
rmsitzandClaude Sonnet 5 5fe3fafc7a Add Outline integration: push lesson notes to a topic collection
Pick a topic on a lesson's note and it pushes to that topic's collection
in a self-hosted Outline instance when you leave the page; notes without a
topic stay local-only. Settings gets a new Outline Integration card
(URL/token, Save, Test Connection).

Credential handling: the API token lives in its own outline_config.json
in DATA_DIR, deliberately kept out of the general settings flow (GET
/api/settings is fetched on every page load by theme.js - no place for a
secret to ride along). GET /api/outline/config only ever returns whether
it's configured, never the token itself.

The topic chooser reflects Outline's live collection list rather than a
locally cached copy, and resolves a newly-typed topic name to a real
collection immediately (find-by-name-or-create) rather than waiting until
the note is pushed. That's not just an optimization: the push itself fires
via navigator.sendBeacon() on pagehide, which can't read a response, so a
page that fires pagehide more than once for the same load (a back/forward-
cache restore, for instance) would otherwise re-send the same "create a
new topic" intent every time and spawn duplicate collections. Verified
live against a local mock Outline server that firing pagehide repeatedly
for the same lesson creates the collection/document once and updates
thereafter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 12:12:50 -04:00
rmsitzandClaude Sonnet 5 a6c49d3762 Add Recently Added, bulk rename, time remaining, library stats, backup export
Five more usability features on top of the search/thumbnails batch:

- Recently Added: dashboard card of courses by folder mtime, separate from
  Recently Viewed (watched vs. just showed up on disk).
- Bulk find/replace rename across every course/folder name at once, with a
  mandatory preview step before anything touches disk. Refactored the
  single-item rename route to share the same validate/apply logic.
- Estimated time remaining on the loaded course's stats card, computed only
  from lessons that have actually reported a duration.
- Library-wide stats overview: total courses, lessons tracked, time
  watched, daily streak - read from each course's small progress file
  rather than re-scanning course contents.
- One-click backup/export zip of settings, hidden-paths, recently-viewed,
  and every course's progress/notes.

Also fixes a real performance bug found along the way: search was routing
through list_library_directory, which computes a full recursive file count
and thumbnail lookup for every course at every level regardless of match -
turning a search into an O(every file in the library) scan. Gave search its
own lightweight directory-only walk (iter_all_courses), now shared by
Recently Added and the stats overview too, so the expensive per-course work
only runs for courses that actually match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 11:36:05 -04:00
rmsitzandClaude Sonnet 5 dbf9528fea Speed up library search on large libraries
search_library_courses was walking via list_library_directory, which
computes a full recursive file count (rglob) and thumbnail lookup for
every course at every level - turning a search into an O(every file in
every course) scan regardless of how few results actually match. Give
search its own lightweight directory-only walk and defer the expensive
per-course lookups until after a name match is confirmed, so cost now
scales with matches found rather than total library size.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 09:22:54 -04:00
rmsitzandClaude Sonnet 5 38963b1d55 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>
2026-08-22 09:06:44 -04:00
rmsitz c92268e04c New mobile layout, new regular screen, added the ability to edit directory names from settings 2026-08-22 08:37:25 -04:00
rmsitz fa00a0b0c4 Fixed themes, empty folder showing and single section course detection 2026-08-21 09:49:44 -04:00
rmsitz 0e9fff65b0 Adding ability to hide / show courses 2026-08-20 20:47:38 -04:00
rmsitz 26a7701968 Moved the add manually box from the main page to the settings page 2026-08-20 20:16:07 -04:00
rmsitz b06b8cf94c Added additional themes 2026-08-20 20:09:58 -04:00
rmsitz f6ec1ad827 Made the header/footer links go back to the main page 2026-08-20 19:58:58 -04:00
rmsitz 699ca7d6df Added some functionality so we can modify the size of the playing video 2026-08-20 19:50:20 -04:00
rmsitz 5b8bef1451 Added a back to main clicking on the link, added help page, added a last 5 viewed 2026-08-20 18:57:27 -04:00
rmsitz 66dff7e69f New main page way of browsing the courses 2026-08-20 18:48:17 -04:00
rmsitz 5c5b068c4c Making the main page folders open and close instead of showing everything 2026-08-20 18:10:54 -04:00
rmsitz c67ab034e0 New header and footer with settings in the bottom 2026-08-20 18:04:48 -04:00
rmsitz 60d81d5b92 Fixed the compose file, it had reverted back to the original 2026-08-20 17:09:57 -04:00
rmsitz a604569a45 Adding a new settings page and other tweaks for how it looks 2026-08-20 17:04:21 -04:00
rmsitz 13de434e6c Fixing some browser weirdness with widths and such 2026-08-20 16:49:54 -04:00
rmsitz fc62d77131 PDF inline fix 1 2026-08-20 16:41:20 -04:00
rmsitz 4066e2f7bd Updating docker-compose with pull_policy 2026-08-20 15:59:27 -04:00
rmsitz 1da1581023 Fix PDF preview rendering as raw text 2026-08-20 15:39:42 -04:00
rmsitz 28202bc016 Updated docker-compose file 2026-08-20 14:46:55 -04:00
rmsitz 6f0fc6cb60 Add library browser feature 2026-08-20 13:47:51 -04:00