TASK 9.4: live chat wiring — right panel with Super Chat + membership badges

- YouTubeStreamService: added GetBroadcastLiveChatIdAsync to fetch liveChatId from broadcast contentDetails
- YouTubeChatService.Poll(): parse snippet.type to handle textMessageEvent, superChatEvent, newSponsorEvent
- MainViewModel: wire _youtubeChat.Start(liveChatId) in PrepareAndStartLiveAsync after broadcast creation
- MainViewModel: wire _youtubeChat.Stop() in StopStream before encoder stop
- MainViewModel: wire _youtubeChat.Dispose() in Shutdown
- MainWindow.xaml: updated chat DataTemplate with member badge (⭐), Super Chat highlight (💰 + gold border), timestamps (HH:mm)
- MainWindow.xaml.cs: auto-scroll ChatListBox on new messages via CollectionChanged
- Chat lifecycle is non-fatal: failures log and the stream continues without on-panel chat
This commit is contained in:
2026-08-19 11:59:29 -07:00
parent e97406d649
commit 1613acadc3
5 changed files with 182 additions and 10 deletions
+25
View File
@@ -1605,6 +1605,7 @@ public class MainViewModel : ViewModelBase
_screenCaptureManager.Dispose();
_layoutStore.Dispose();
_musicPlayer.Dispose();
_youtubeChat.Dispose();
}
public void SaveLayoutNow()
@@ -2236,6 +2237,27 @@ public class MainViewModel : ViewModelBase
return;
}
AppLog.Write($"Broadcast created: {_currentBroadcastId}");
// Start chat polling (TASK 9.4): fetch the liveChatId from the broadcast's
// contentDetails, then start the poll loop. Chat is non-fatal — if it fails,
// the stream continues without on-panel chat.
try
{
var liveChatId = await _youtubeStream.GetBroadcastLiveChatIdAsync(_currentBroadcastId);
if (liveChatId != null)
{
_youtubeChat.Start(liveChatId);
AppLog.Write($"Chat polling started: {liveChatId}");
}
else
{
AppLog.Write("Could not retrieve liveChatId; chat polling disabled");
}
}
catch (Exception chatEx)
{
AppLog.Write($"Chat start failed (non-fatal): {chatEx.Message}");
}
}
catch (Exception ex)
{
@@ -2302,6 +2324,9 @@ public class MainViewModel : ViewModelBase
StreamStatus = StreamStatus.Offline;
WindowTitle = "ytLlive";
ResetHealth(StreamStatus.Offline);
// Stop chat polling first (TASK 9.4) — no more messages arriving while
// we're tearing down the stream.
_youtubeChat.Stop();
// Close the audio pipe FIRST so ffmpeg sees EOF on the audio input,
// then stop the pump (stdin EOF) — both inputs end and the encoder
// finalizes the FLV. Audio capture itself is always-on (preview