feat(entitlement): gate 60 fps output through Steam

This commit is contained in:
2026-11-04 12:14:46 -08:00
parent 1993e7cc8b
commit 7216c95449
12 changed files with 188 additions and 72 deletions
+14 -1
View File
@@ -1,4 +1,5 @@
using ytLive.Helpers;
using ytLive.Models;
using ytLive.Services.Entitlement;
namespace ytLive.ViewModels;
@@ -13,17 +14,28 @@ public partial class MainViewModel
{
private IEntitlement _entitlement = CreateEntitlement();
private bool _isAppOwned;
private string? _entitlementErrorMessage;
public bool IsAppOwned
{
get => _isAppOwned;
private set
{
if (!SetProperty(ref _isAppOwned, value)) return;
var changed = SetProperty(ref _isAppOwned, value);
EntitlementErrorMessage = _entitlement.ErrorMessage;
if (!changed) return;
OnPropertyChanged(nameof(HasProOutput));
if (!HasProOutput && _selectedQuality is { RequiresPro: true } && CanChangeQuality)
SelectedQuality = QualityOptions.Single(option => option.Display == OutputProfile.FreeFallbackName);
}
}
public string? EntitlementErrorMessage
{
get => _entitlementErrorMessage;
private set => SetProperty(ref _entitlementErrorMessage, value);
}
public bool HasProOutput => DeveloperMode || IsAppOwned;
private static IEntitlement CreateEntitlement()
@@ -43,6 +55,7 @@ public partial class MainViewModel
{
_entitlement = value;
IsAppOwned = value.IsAppOwned;
EntitlementErrorMessage = value.ErrorMessage;
}
}
+9 -1
View File
@@ -66,6 +66,7 @@ public partial class MainViewModel : ViewModelBase
{
_youtubeBroadcastLive = false;
OnPropertyChanged(nameof(IsOffline));
OnPropertyChanged(nameof(CanChangeQuality));
OnPropertyChanged(nameof(IsLive));
OnPropertyChanged(nameof(IsEditMode));
OnPropertyChanged(nameof(RecDotBrush));
@@ -91,6 +92,7 @@ public partial class MainViewModel : ViewModelBase
public bool IsOffline => StreamStatus == StreamStatus.Offline;
public bool IsLive => StreamStatus == StreamStatus.Streaming;
public bool CanChangeQuality => IsOffline && !IsRecording;
public bool IsLivePrivate => IsLive && string.Equals(StreamVisibility, "Private", StringComparison.OrdinalIgnoreCase);
public string RecDotBrush => !IsRecording
? ThemeBrush.Hex("Brush.OnSurfaceDisabled")
@@ -151,6 +153,7 @@ public partial class MainViewModel : ViewModelBase
internal set
{
if (!SetProperty(ref _isRecording, value)) return;
OnPropertyChanged(nameof(CanChangeQuality));
OnPropertyChanged(nameof(RecDotBrush));
OnPropertyChanged(nameof(RecTextBrush));
OnPropertyChanged(nameof(RecDotOpacity));
@@ -450,10 +453,15 @@ public partial class MainViewModel : ViewModelBase
get => _selectedQuality;
set
{
if (!CanChangeQuality)
{
OnPropertyChanged(nameof(SelectedQuality));
return;
}
if (!HasProOutput && value.RequiresPro)
{
OnPropertyChanged(nameof(SelectedQuality));
OpenAboutCommand.Execute(null);
return;
}
+4 -1
View File
@@ -200,7 +200,10 @@ public partial class MainViewModel : ViewModelBase
_youtubeChat = new YouTubeChatService(_youtubeAuth);
AppLog.Write("MainViewModel ctor: services created");
_selectedQuality = OutputProfile.Resolve(QualityOptions[0], QualityOptions, HasProOutput);
var defaultQuality = HasProOutput
? QualityOptions[0]
: QualityOptions.Single(option => option.Display == OutputProfile.FreeFallbackName);
_selectedQuality = OutputProfile.Resolve(defaultQuality, QualityOptions, HasProOutput);
ApplyStreamQuality(_selectedQuality);
_youtubeChat.MessageReceived += OnChatMessageReceived;