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
+82 -8
View File
@@ -980,16 +980,90 @@
ItemsSource="{Binding ChatMessages}"
ItemContainerStyle="{StaticResource YtListBoxItem}"
Visibility="{Binding ShowChatInactiveMessage, Converter={StaticResource InverseBoolToVis}}"
Foreground="#e0e0e0" FontSize="12">
Foreground="#e0e0e0" FontSize="12"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
x:Name="ChatListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,2">
<TextBlock>
<Run Text="{Binding AuthorName, Mode=OneWay}" FontWeight="Bold" Foreground="#e94560"/>
<Run Text=": "/>
<Run Text="{Binding Message, Mode=OneWay}" Foreground="#e0e0e0"/>
</TextBlock>
</StackPanel>
<Border x:Name="MessageBorder" Padding="6,4" CornerRadius="4" Margin="0,1">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSuperChat}" Value="True">
<Setter Property="Background" Value="#2a1a0a"/>
<Setter Property="BorderBrush" Value="#eab308"/>
<Setter Property="BorderThickness" Value="1,0,1,0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel>
<StackPanel Orientation="Horizontal">
<!-- Member badge -->
<TextBlock Text="⭐" FontSize="10" Margin="0,0,3,0"
VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMember}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<!-- Author name -->
<TextBlock FontWeight="Bold" Foreground="#e94560"
Text="{Binding AuthorName, Mode=OneWay}"
VerticalAlignment="Center"/>
<!-- Super Chat amount -->
<TextBlock Foreground="#eab308" FontWeight="Bold"
FontSize="11" Margin="6,0,0,0"
VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSuperChat}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
<Run Text="💰 $"/>
<Run Text="{Binding SuperChatAmount, Mode=OneWay, StringFormat=F2}"/>
<Run Text="{Binding SuperChatCurrency, Mode=OneWay}"/>
</TextBlock>
<!-- Timestamp -->
<TextBlock Foreground="#555" FontSize="10"
Margin="6,0,0,0" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Timestamp}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
<TextBlock.Text>
<Binding Path="Timestamp" StringFormat="{}{0:HH:mm}"/>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<!-- Message -->
<TextBlock Text="{Binding Message, Mode=OneWay}"
Foreground="#e0e0e0" TextWrapping="Wrap"
Margin="0,2,0,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>