a9d5f29084
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.
36 lines
1.4 KiB
C#
36 lines
1.4 KiB
C#
using ytLive.Services;
|
|
|
|
namespace ytLive.ViewModels;
|
|
|
|
public partial class MainViewModel
|
|
{
|
|
/// <summary>Test seam (mirrors CameraEnumeratorOverride): tests inject a fake
|
|
/// stats service before constructing the VM so refresh never hits the network.</summary>
|
|
internal static Func<ChannelStatsService>? ChannelStatsFactoryOverride { get; set; }
|
|
|
|
/// <summary>The YPP pull-out backing VM — the drawer below Stream Settings
|
|
/// on the Live screen's right edge (TASK 39).</summary>
|
|
public Services.YppTrackerViewModel Ypp { get; private set; } = null!;
|
|
|
|
private void InitYpp()
|
|
{
|
|
Ypp = new YppTrackerViewModel(
|
|
() => _layoutStore,
|
|
() => ChannelStatsFactoryOverride?.Invoke() ?? new ChannelStatsService(_youtubeAuth),
|
|
() => IsConnected,
|
|
() => _youtubeAuth.CurrentChannel?.DisplayName);
|
|
|
|
// One drawer at a time: the two pull-outs share the preview's right edge,
|
|
// so opening one collapses the other (both directions).
|
|
BroadcastForm.PropertyChanged += (_, e) =>
|
|
{
|
|
if (e.PropertyName == nameof(LiveBroadcastFormViewModel.IsDrawerOpen) && BroadcastForm.IsDrawerOpen)
|
|
Ypp.IsDrawerOpen = false;
|
|
};
|
|
Ypp.PropertyChanged += (_, e) =>
|
|
{
|
|
if (e.PropertyName == nameof(YppTrackerViewModel.IsDrawerOpen) && Ypp.IsDrawerOpen)
|
|
BroadcastForm.IsDrawerOpen = false;
|
|
};
|
|
}
|
|
} |