Fixes #21 — Curated YouTube videos per guide + grammar item

Each of the 56 tense guides and grammar notes gets a curated YouTube video
attached (54 with picks, 2 silent nulls on rare / hard-to-find topics).
Users can stream in YouTube/Safari, download via YouTubeKit for offline
viewing, or play the local MP4 full-screen via AVPlayer.

YouTubeVideoStore loads the bundled youtube_videos.json at launch and serves
lookups by tense id or grammar note id. VideoDownloadService resolves the
best progressive MP4 stream off the main actor (YouTubeKit isn't Sendable),
writes to documents/videos/<videoId>.mp4, and records a DownloadedVideo row
in the local SwiftData container so the app knows what's on disk across
launches.

VideoActionsButtonRow is the unified UI for both detail views: three large
buttons — Stream (red, always enabled), Download (blue, disabled while in
flight and after completion, shows progress), Play (green, enabled only
when downloaded). Full-screen cover on tap. Settings gains a Downloaded
Videos list with swipe-delete, total-size summary, and a 500 MB warning.

Local store reset version bumped to 4 for the new DownloadedVideo schema.

Known fragility: YouTubeKit scrapes YouTube's private stream API and will
break when YouTube changes their internal format. Streaming keeps working
regardless.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-04-22 18:51:19 -05:00
parent 98badc98ad
commit 5777a210cd
13 changed files with 750 additions and 1 deletions

View File

@@ -28,6 +28,9 @@ schemes:
packages:
SharedModels:
path: SharedModels
YouTubeKit:
url: https://github.com/alexeichhorn/YouTubeKit.git
from: 0.3.0
settings:
base:
@@ -49,6 +52,8 @@ targets:
buildPhase: resources
- path: Conjuga/reflexive_verbs.json
buildPhase: resources
- path: Conjuga/youtube_videos.json
buildPhase: resources
info:
path: Conjuga/Info.plist
properties:
@@ -80,6 +85,7 @@ targets:
dependencies:
- target: ConjugaWidgetExtension
- package: SharedModels
- package: YouTubeKit
ConjugaWidgetExtension:
type: app-extension