Creator design (2026-11-05). A stack of red rows at the top of the left panel, above both mode grids so it shows while editing and while live, pushing the panel's content down. - Row 1 is the **Steam licence indicator** and nothing displaces it. It reads as status, not a warning: "Entitlement 30 fps · Maximum 60 fps", both numbers derived from QualityOptions and HasProOutput. While higher tiers are unavailable it shows a **pin** (standing indicator, no close control); once ownership is verified the pin becomes a **close control** and the dismissal is persisted (`Steam.LicenceIndicatorDismissed`), permanent while ownership holds. Losing ownership restores it as pinned — a change of state, not a preference. Click → About. - **Event rows stack beneath, newest first**, one row per episode (an episode advancing its state updates its own row rather than adding another). Each is dismissible. Click → the Logs tab opens with that event's sequence range painted red (`HighlightedLogFrom/To` + `LogInRangeConverter`; two numbers rather than a collection because the log list is virtualised and realised rows do not re-evaluate on membership changes). - Replaces the old red panel under the quality picker, which is removed. - The Steam diagnostic text loses "Contact the creator or support" for a neutral "Steam licensing is not configured in this build." Tests: `AttentionAlertStackTests` — pinned first with the status text; owned → closable and the close survives a reload but ownership loss restores it pinned; pinned cannot be dismissed; event rows LIFO with in-place episode updates; clicking an event opens Logs and sets its range. AboutHub + Entitlement tests updated for the removed panel and the new wording. FAST gate: 532 passed, 0 failed, 0 warnings.
85 lines
2.6 KiB
C#
85 lines
2.6 KiB
C#
using ytLive.Helpers;
|
|
using ytLive.Models;
|
|
using ytLive.Services.Entitlement;
|
|
|
|
namespace ytLive.ViewModels;
|
|
|
|
/// <summary>
|
|
/// The app-wide Steam ownership flag and its output-profile consumer.
|
|
///
|
|
/// <para>Only the entitlement service decides whether the current Steam account owns the paid app.
|
|
/// Development builds use a fake owned result; Release builds use Steam.</para>
|
|
/// </summary>
|
|
public partial class MainViewModel
|
|
{
|
|
private IEntitlement _entitlement = CreateEntitlement();
|
|
private bool _isAppOwned;
|
|
private string? _entitlementErrorMessage;
|
|
|
|
public bool IsAppOwned
|
|
{
|
|
get => _isAppOwned;
|
|
private set
|
|
{
|
|
var changed = SetProperty(ref _isAppOwned, value);
|
|
EntitlementErrorMessage = _entitlement.ErrorMessage;
|
|
if (!changed) return;
|
|
OnPropertyChanged(nameof(HasProOutput));
|
|
RefreshSteamLicenceAlert();
|
|
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()
|
|
{
|
|
#if DEBUG
|
|
return new FakeEntitlement(true);
|
|
#else
|
|
return SteamEntitlement.NotConfigured();
|
|
#endif
|
|
}
|
|
|
|
/// <summary>Test seam: swap the ownership source without a Steam client.</summary>
|
|
internal IEntitlement EntitlementOverride
|
|
{
|
|
get => _entitlement;
|
|
set
|
|
{
|
|
_entitlement = value;
|
|
IsAppOwned = value.IsAppOwned;
|
|
EntitlementErrorMessage = value.ErrorMessage;
|
|
}
|
|
}
|
|
|
|
private bool _developerMode;
|
|
|
|
/// <summary>
|
|
/// Development-only override: ignore the output budget and allow every shipped tier.
|
|
///
|
|
/// <para>There is no UI to reach this in a Release build — the panel that hosts the
|
|
/// checkbox is excluded from the Release compile — and the setter refuses the value
|
|
/// unless <see cref="DevBuild.IsDevelopment"/> is true, so even a hand-edited settings
|
|
/// file cannot unlock it.</para>
|
|
/// </summary>
|
|
public bool DeveloperMode
|
|
{
|
|
get => _developerMode;
|
|
set
|
|
{
|
|
if (!DevBuild.IsDevelopment) return;
|
|
if (!SetProperty(ref _developerMode, value)) return;
|
|
OnPropertyChanged(nameof(HasProOutput));
|
|
RefreshSteamLicenceAlert();
|
|
}
|
|
}
|
|
}
|