feat(ypp): YPP journey tracker slice 1 — the YPP pull-out below Stream Settings (TASK 39, Good Dog ONE test)
Current-OAuth-scope data, no re-consent: subscriber bars for both tiers (500 fan-funding / 1,000 ad-revenue; the 2027-02-01 doubling is versioned date-aware data in YppThresholds), 3-uploads/90d, live standing from channels.list auditDetails, self-reported 2FA/AdSense checkboxes + deep links (Google 2-Step / youtube.com/earn), and the "what counts" education. Every refresh appends a YppSnapshot (SQLite v10) so the analytics slice has history from day one. - ChannelStatsService (channels.list statistics,auditDetails,contentDetails + playlistItems.list, virtual CaptureCurrentAsync = test seam); YppTrackerViewModel mirrors LiveBroadcastFormViewModel. - MainViewModel.Ypp.cs: Ypp property, ChannelStatsFactoryOverride seam, one-open-at-a-time drawer exclusivity (both directions); account sign-in/out/restore hooks in Account.cs. - PreviewPane.xaml: TextPullOutHost is now a drawer bank [broadcast][ypp][stacked white tabs]; outside-click collapse covers both drawers. MainWindow.xaml.cs updated. - Wait - watchers: the whole feature already reviewed against YouTube's own docs (YPP Earn tab + API availability) before building — see TASKS/task-39-ypp-journey-tracker.md. - ONE integration test: YppPullOutTests (snapshot capture/persist + checklist round-trip + drawer exclusivity). 313/313 pass, 0 warnings. - Memory in same commit: TASKS.md row, ai.md Journey-tracker bullet (roadmap→reality), HANDOFF.md. Slice 2 (Analytics yt-analytics.readonly re-consent → watch-hours/Shorts + velocity/ETA + sparkline) is queued behind this, not merged.
This commit is contained in:
@@ -1439,16 +1439,21 @@ removal above). It has three layers, all free — this is the product's differen
|
||||
reward totals (new members, Super Chat $, stickers $, gifts, milestones). This is the in-app
|
||||
replacement for the emailed external "stream activity report" — the incumbents (Streamlabs et al.)
|
||||
email near-useless post-stream summaries; we track the same data natively and maintain it.
|
||||
- **Journey tracker.** On sign-in/startup, pull current `channels.list?mine=true&part=statistics`
|
||||
(`subscriberCount`/`viewCount`/`videoCount` — the current OAuth scopes suffice). Compute position
|
||||
toward each YPP tier threshold and project an ETA curve from the creator's own
|
||||
per-stream/per-day velocity (subs + watch hours). **YPP thresholds are versioned, date-aware DATA,
|
||||
never constants** — the Tier-2 bar doubles for new applicants on **2027-02-01** (long-form 4,000 →
|
||||
8,000 qualified hrs / 365d; Shorts 10M → 20M / 90d), while the Tier-1 fan-funding bar (500 subs /
|
||||
3,000 hrs / 3M Shorts) is unchanged. Hardcoding the pre-2027 numbers would ship a wrong ETA.
|
||||
Analytics-API scopes (`yt-analytics.readonly`, additive `yt-analytics-monetary.readonly`) are an
|
||||
additive capability behind a seam (`IChannelStatsProvider`), not a v1 blocker — current-scope data
|
||||
is the v1 baseline; the Analytics scopes would require an OAuth re-consent, deferred.
|
||||
- **Journey tracker (TASK 39, slice 1 shipped 2026-09-22).** A **"YPP"** tab below the
|
||||
Stream Settings pull-out (Live screen right edge) shows the connected creator's position
|
||||
toward each YPP tier threshold. Slice 1 = current-scope data only: `channels.list?mine=true
|
||||
&part=statistics,auditDetails,contentDetails` (subs/views/videos + uploads-playlist id +
|
||||
live standing flags) + `playlistItems.list` for 90-day public uploads. Every refresh appends
|
||||
a `YppSnapshot` to SQLite (schema v10) — the history a later slice needs for velocity/ETA.
|
||||
**YPP thresholds are versioned, date-aware DATA, never constants** — the Tier-2 bar doubles
|
||||
for new applicants on **2027-02-01** (long-form 4,000 → 8,000 qualified hrs / 365d; Shorts
|
||||
10M → 20M / 90d), while the Tier-1 fan-funding bar (500 subs / 3,000 hrs / 3M Shorts) is
|
||||
unchanged. Hardcoding the pre-2027 numbers would ship the wrong ETA. Watch-hours / Shorts /
|
||||
velocity / ETA are **slice 2**: Analytics-API scopes (`yt-analytics.readonly`, additive
|
||||
`yt-analytics-monetary.readonly`) behind the `IChannelStatsProvider` seam (additive
|
||||
capability, requires an OAuth re-consent). Compliance items no API exposes (2FA, AdSense
|
||||
linkage) are in-app self-reported checkboxes with deep links; standing checks are live from
|
||||
`auditDetails`. Slice 2's once-daily refresh gate + snapshot history were baked into slice 1.
|
||||
|
||||
**What was rejected:** always-on watermark (obscurable — replaced by the flash), hard stream-time
|
||||
cutoffs (the worst dead end — a stream dying mid-broadcast reads as broken, and YouTube streams
|
||||
|
||||
Reference in New Issue
Block a user