feat(ui): color and acknowledge pinned log errors
Add independent AppLog message types and explicit Class 1/2 severity. Wrap and color log rows, pin Class 1 above Class 2, and let acknowledgement return entries to the current-launch timeline without changing file format or rotation. Ref: https://logtape.org/manual/levels
This commit is contained in:
@@ -159,7 +159,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
var stream = await _youtubeStream.GetOrCreateReusableStreamAsync();
|
||||
if (stream == null)
|
||||
{
|
||||
AppLog.Write("Reusable stream unavailable; check the OAuth session");
|
||||
AppLog.Write("Reusable stream unavailable; check the OAuth session",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
_notifications.Error("Couldn't go live",
|
||||
"The reusable stream is unavailable — check the YouTube sign-in and try again.");
|
||||
StopStream(); // full rollback — audio loop + recording + pills, no Error-status zombie
|
||||
@@ -174,12 +175,13 @@ public partial class MainViewModel : ViewModelBase
|
||||
_broadcastSeenLive = false;
|
||||
if (_currentBroadcastId == null)
|
||||
{
|
||||
AppLog.Write("Broadcast creation failed; check the OAuth session");
|
||||
AppLog.Write("Broadcast creation failed; check the OAuth session",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
_notifications.Error("Couldn't go live", "YouTube rejected the broadcast — check the sign-in and try again.");
|
||||
StopStream(); // full rollback
|
||||
return;
|
||||
}
|
||||
AppLog.Write($"Broadcast created: {_currentBroadcastId}");
|
||||
AppLog.WriteSuccess($"Broadcast created: {_currentBroadcastId}");
|
||||
OnPropertyChanged(nameof(CurrentBroadcastId));
|
||||
|
||||
// ⛔ THE BINDING — the call whose absence is why nothing ever went live
|
||||
@@ -198,7 +200,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
var bindError = await _youtubeStream.BindBroadcastAsync(_currentBroadcastId, stream.Id);
|
||||
if (bindError != null)
|
||||
{
|
||||
AppLog.Write($"Stream binding failed: {bindError}");
|
||||
AppLog.Write($"Stream binding failed: {bindError}",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
// Show the real reason. "Check the sign-in" would be wrong for five of the
|
||||
// six documented bind failures, and would hide our own ordering bug behind
|
||||
// a plausible excuse — see BindFailureMessage.
|
||||
@@ -216,7 +219,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppLog.Write($"Go-live preparation failed: {ex.Message}");
|
||||
AppLog.Write($"Go-live preparation failed: {ex.Message}",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
_notifications.Error("Couldn't go live", ex.Message);
|
||||
StopStream(); // full rollback — a created broadcast (if any) gets the close-out
|
||||
return;
|
||||
@@ -242,12 +246,14 @@ public partial class MainViewModel : ViewModelBase
|
||||
}
|
||||
else
|
||||
{
|
||||
AppLog.Write("Could not retrieve liveChatId; chat polling disabled");
|
||||
AppLog.Write("Could not retrieve liveChatId; chat polling disabled",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
}
|
||||
}
|
||||
catch (Exception chatEx)
|
||||
{
|
||||
AppLog.Write($"Chat start failed (non-fatal): {chatEx.Message}");
|
||||
AppLog.Write($"Chat start failed (non-fatal): {chatEx.Message}",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
}
|
||||
|
||||
// TASK 41: a test broadcast hands its session to the Test drawer once
|
||||
@@ -285,7 +291,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
var health = await _youtubeStream.GetStreamHealthAsync(_reusableStream.Id);
|
||||
if (health == null)
|
||||
{
|
||||
AppLog.Write("Stream health poll failed; check the OAuth session");
|
||||
AppLog.Write("Stream health poll failed; check the OAuth session",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
return;
|
||||
}
|
||||
CurrentHealth.HealthStatus = health.HealthStatus;
|
||||
@@ -303,7 +310,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppLog.Write($"Stream health poll failed: {ex.Message}");
|
||||
AppLog.Write($"Stream health poll failed: {ex.Message}",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,7 +383,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
{
|
||||
var closeOutError = await _youtubeStream.EndBroadcastAsync(endedBroadcastId);
|
||||
if (closeOutError != null)
|
||||
AppLog.Write($"End close-out: {closeOutError} — enableAutoStop will finish the broadcast");
|
||||
AppLog.Write($"End close-out: {closeOutError} — enableAutoStop will finish the broadcast",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
}
|
||||
|
||||
_currentBroadcastId = null;
|
||||
@@ -435,7 +444,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
// with IsRecording=true and no encoder (first real launch proved it). The
|
||||
// failure now runs the NORMAL stop path on the UI thread (pills off, audio
|
||||
// loop closed, recording finalized, close-out if live), then explains itself.
|
||||
AppLog.Write($"Frame pump failed: {message}");
|
||||
AppLog.Write($"Frame pump failed: {message}", AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
void Handle()
|
||||
{
|
||||
var live = IsLive;
|
||||
@@ -567,7 +576,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
_notifications.Info("Broadcast deleted", "The broadcast was removed from YouTube.");
|
||||
break;
|
||||
case PrivateBroadcastOutcome.DeleteFailed:
|
||||
AppLog.Write($"Private broadcast delete failed: {broadcastId}: {error}");
|
||||
AppLog.Write($"Private broadcast delete failed: {broadcastId}: {error}",
|
||||
AppLogMessageType.Error, AppLogErrorClass.Class2);
|
||||
_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;
|
||||
|
||||
Reference in New Issue
Block a user