OAuth session persists via DPAPI; sign-in lives in the Start Stream dialog; add xUnit test project (6 passing)
This commit is contained in:
@@ -47,7 +47,7 @@ C# / WPF (.NET 8) following MVVM:
|
||||
| `Models/` | Plain data types — Scene, Source, QualityOption, StreamConfig, StreamHealth, YouTubeChannel, ChatMessage |
|
||||
| `ViewModels/` | MainViewModel — exposes collections + commands for the UI; GoLiveViewModel, ReuseImageViewModel |
|
||||
| `Services/` | YouTube OAuth2, stream/broadcast management, live chat polling, LayoutStore (SQLite) |
|
||||
| `Helpers/` | ViewModelBase (INotifyPropertyChanged), RelayCommand, ImageCache, AppLog (file logger), FocusPreservingListBox, OAuthCredentials, visibility converters |
|
||||
| `Helpers/` | ViewModelBase (INotifyPropertyChanged), RelayCommand, ImageCache, AppLog (file logger), FocusPreservingListBox, OAuthCredentials, **TokenStore (DPAPI session persistence)**, visibility converters |
|
||||
| `Themes/` | `Controls.xaml` — the single dark-theme source, merged once in `App.xaml` (see `Themes/index.md`) |
|
||||
| `MainWindow.xaml` | Dark theme; layout: top bar (controls), center (preview), left (scenes/sources), right (chat), bottom (health) |
|
||||
|
||||
@@ -64,9 +64,8 @@ C# / WPF (.NET 8) following MVVM:
|
||||
|
||||
### Current limitations / TODOs
|
||||
|
||||
- `Helpers/OAuthCredentials.cs` now contains the real ClientId/ClientSecret — auth service is implemented, but **tokens still don't persist** (Windows DPAPI planned; account UI in the GoLive dialog is simulated)
|
||||
- `GoLiveViewModel.SignIn`/`ChangeAccount` removed — Connect (OAuth) is the only entry to streaming
|
||||
- Scene/source/asset layout *does* persist (SQLite); token persistence does not (yet)
|
||||
- `Helpers/OAuthCredentials.cs` contains the real ClientId/ClientSecret. Auth is complete and the session **persists via Windows DPAPI** (`Helpers/TokenStore.cs` → `%APPDATA%\ytLlive\ytLlive.auth`, CurrentUser scope), reloaded best-effort at startup with a proactive refresh of a near-expiry access token. Sign-in/Change Account lives **inside the Start Stream dialog** (two-state flow — no separate Connect button). `YouTubeAuthService` takes an optional `HttpClient` + `sessionChanged` callback (test seam + save hook; services are still constructed in `MainViewModel`)
|
||||
- Scene/source/asset layout persists (SQLite); the OAuth session persists (DPAPI); the paid-unlock state does not (yet — itch.io key verification pending)
|
||||
- `YouTubeStreamService` uses hardcoded `1080p`/`60fps` and per-broadcast streams — must switch to the v3 `variable` reusable stream
|
||||
- No capture/encoding/RTMP yet
|
||||
- `StreamConfig` defaults (`TargetBitrate=6000`, `Resolution="1920x1080"`) are stale — the live dropdown drives `StreamHealth.CurrentBitrate`/`FPS` instead
|
||||
@@ -106,16 +105,19 @@ resolution & streaming-constraints conversation, not monetization.
|
||||
|
||||
The app is fully usable without authentication: users can build scenes, add sources, compose
|
||||
previews, and audition the software with zero commitment. But **going live requires authentication** —
|
||||
it's the one capability gated behind YouTube sign-in. The sign-in button should never pressure the
|
||||
user ("sign in (optional)", not a modal wall), but "Go Live" only appears once connected.
|
||||
it's the one capability gated behind YouTube sign-in. The sign-in should never pressure the user
|
||||
("sign in (optional)", not a modal wall): the two-state top bar shows **Start Stream** (offline) /
|
||||
**End Stream** (live), and the Start Stream dialog hosts the account — a saved session appears as
|
||||
the default with "Change Account"; with none saved, a "Sign in to YouTube" button starts OAuth and
|
||||
the Start button stays disabled until signed in.
|
||||
|
||||
## Account assumption (do not build an account setup flow)
|
||||
|
||||
Connecting uses Google OAuth ("Sign in with Google") to link an **existing** YouTube creator
|
||||
account. ytLlive **never creates or sets up accounts** — that is YouTube's job. If the creator has no
|
||||
YouTube channel, they go to YouTube first. This assumption is explicit and must never be silently
|
||||
replaced by an in-app account-creation step. Zero state = a Connect button that starts OAuth; going
|
||||
live is unreachable until the account is connected.
|
||||
replaced by an in-app account-creation step. Zero state = the Start Stream dialog's "Sign in to
|
||||
YouTube" button; going live is unreachable until an account is connected.
|
||||
|
||||
## YouTube Live API — design constraints (do not violate)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user