Private broadcasts end like recordings: Enter keeps, Escape deletes (KeepBroadcastDialog). Privacy read from YouTube; delete = videos.delete (fallback liveBroadcasts.delete on 404). Refs: https://developers.google.com/youtube/v3/docs/videos/delete https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/delete (Unit: private broadcast close-out)
This commit is contained in:
@@ -360,9 +360,10 @@ public partial class MainViewModel : ViewModelBase
|
||||
// finalizes the VOD immediately instead of leaving viewers on a frozen
|
||||
// "stream offline" until enableAutoStop fires (~1 min). Log-only failure:
|
||||
// the backstop still ends the broadcast; a stop never fails over cosmetics.
|
||||
if (wasLive && _currentBroadcastId != null)
|
||||
var endedBroadcastId = wasLive ? _currentBroadcastId : null;
|
||||
if (endedBroadcastId != null)
|
||||
{
|
||||
var closeOutError = await _youtubeStream.EndBroadcastAsync(_currentBroadcastId);
|
||||
var closeOutError = await _youtubeStream.EndBroadcastAsync(endedBroadcastId);
|
||||
if (closeOutError != null)
|
||||
AppLog.Write($"End close-out: {closeOutError} — enableAutoStop will finish the broadcast");
|
||||
}
|
||||
@@ -370,6 +371,11 @@ public partial class MainViewModel : ViewModelBase
|
||||
_currentBroadcastId = null;
|
||||
OnPropertyChanged(nameof(CurrentBroadcastId));
|
||||
|
||||
// Creator ruling 2026-10-09: a PRIVATE broadcast ends like a recording — Enter keeps
|
||||
// it on YouTube, Escape deletes it.
|
||||
if (endedBroadcastId != null)
|
||||
await OfferToKeepPrivateBroadcastAsync(endedBroadcastId);
|
||||
|
||||
if (wasRecording) await FinalizeRecordingAsync();
|
||||
|
||||
// Explicit sign-out only (TASK 18): stopping the stream does NOT clear
|
||||
@@ -519,4 +525,49 @@ public partial class MainViewModel : ViewModelBase
|
||||
_recDotPulse = _recDotPulse > 0.5 ? 0.35 : 1.0;
|
||||
OnPropertyChanged(nameof(RecDotOpacity));
|
||||
}
|
||||
|
||||
/// <summary>What happened to a finished broadcast at the keep-or-delete prompt.</summary>
|
||||
internal enum PrivateBroadcastOutcome { NotPrivate, Kept, Deleted, DeleteFailed }
|
||||
|
||||
/// <summary>Test seam: answers the keep-or-delete prompt (title → keep?) instead of showing
|
||||
/// <see cref="KeepBroadcastDialog"/>. Mirrors the other static overrides.</summary>
|
||||
internal static Func<string, bool>? KeepBroadcastPromptOverride { get; set; }
|
||||
|
||||
private async Task OfferToKeepPrivateBroadcastAsync(string broadcastId)
|
||||
{
|
||||
var title = BroadcastForm.Title;
|
||||
var (outcome, error) = await ClosePrivateBroadcastAsync(_youtubeStream, broadcastId,
|
||||
() => KeepBroadcastPromptOverride?.Invoke(title) ?? new KeepBroadcastDialog(title).ShowDialog() == true);
|
||||
switch (outcome)
|
||||
{
|
||||
case PrivateBroadcastOutcome.Kept:
|
||||
AppLog.Write($"Private broadcast kept: {broadcastId}");
|
||||
_notifications.Info("Broadcast kept", "It's on YouTube as a private video.");
|
||||
break;
|
||||
case PrivateBroadcastOutcome.Deleted:
|
||||
AppLog.Write($"Private broadcast deleted by creator: {broadcastId}");
|
||||
_notifications.Info("Broadcast deleted", "The broadcast was removed from YouTube.");
|
||||
break;
|
||||
case PrivateBroadcastOutcome.DeleteFailed:
|
||||
AppLog.Write($"Private broadcast delete failed: {broadcastId}: {error}");
|
||||
_notifications.Error("Couldn't delete the broadcast",
|
||||
$"{error}. It's still on YouTube as a private video — you can delete it in YouTube Studio.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The keep-or-delete decision for a finished broadcast. Asks ONLY when YouTube
|
||||
/// itself reports the broadcast as private (visibility can change mid-stream, so local state
|
||||
/// isn't trusted); an unreadable status asks nothing and deletes nothing. Keep = leave it;
|
||||
/// otherwise delete the video from YouTube.</summary>
|
||||
internal static async Task<(PrivateBroadcastOutcome Outcome, string? Error)> ClosePrivateBroadcastAsync(
|
||||
YouTubeStreamService youtube, string broadcastId, Func<bool> askKeep)
|
||||
{
|
||||
var privacy = await youtube.GetBroadcastPrivacyAsync(broadcastId);
|
||||
if (!string.Equals(privacy, "private", StringComparison.OrdinalIgnoreCase))
|
||||
return (PrivateBroadcastOutcome.NotPrivate, null);
|
||||
if (askKeep()) return (PrivateBroadcastOutcome.Kept, null);
|
||||
var error = await youtube.DeleteFinishedBroadcastAsync(broadcastId);
|
||||
return error == null ? (PrivateBroadcastOutcome.Deleted, null) : (PrivateBroadcastOutcome.DeleteFailed, error);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user