feat: Elements panel, Countdown/Web sources, webcam border config (TASK 14 Branch 2)
- New SourceType.Countdown (Starting/BRB only, timer 1-60 min) and SourceType.WebSource (all scenes, URI) - Elements panel beneath Sources: per-element config with live preview, ✕ revert / ✓ applied indicator - Webcam border: hex color input + swatch picker, thickness 0-10 slider - Countdown: timer minutes slider (1-60, default 15), Web: URI text input - SourceTypeToVisibilityConverter for conditional panel visibility - Snapshot/revert mechanism in code-behind for live-preview cancel
This commit is contained in:
+107
@@ -37,6 +37,11 @@
|
||||
xmlns:Helpers="clr-namespace:ytLive.Helpers"/>
|
||||
<Helpers:EnumToBoolConverter x:Key="EnumToBool"
|
||||
xmlns:Helpers="clr-namespace:ytLive.Helpers"/>
|
||||
<Helpers:SourceTypeToVisibilityConverter x:Key="SourceTypeToCountdownVis"
|
||||
xmlns:Helpers="clr-namespace:ytLive.Helpers"
|
||||
xmlns:models2="clr-namespace:ytLive.Models"/>
|
||||
<Helpers:SourceTypeToVisibilityConverter x:Key="SourceTypeToWebVis"
|
||||
xmlns:Helpers="clr-namespace:ytLive.Helpers"/>
|
||||
|
||||
<!-- Red dot shown in the taskbar icon while live -->
|
||||
<DrawingImage x:Key="LiveOverlay">
|
||||
@@ -162,6 +167,9 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Scenes: the app has five canonical scenes. Work with less,
|
||||
@@ -236,6 +244,11 @@
|
||||
<MenuItem Header="Background" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.Background}"/>
|
||||
<MenuItem Header="Image" Command="{Binding AddImageCommand}"/>
|
||||
<MenuItem Header="Text" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.TextOverlay}"/>
|
||||
<MenuItem Header="Countdown" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.Countdown}"
|
||||
Visibility="{Binding IsCountdownAvailable, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="Timer overlay — Starting and BRB scenes only"/>
|
||||
<MenuItem Header="Web" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.WebSource}"
|
||||
ToolTip="Embedded web page — set URI in Elements panel"/>
|
||||
</ContextMenu>
|
||||
</Button.ContextMenu>
|
||||
<Path Data="M12,4 L12,20 M4,12 L20,12" Stroke="#e94560" StrokeThickness="2"
|
||||
@@ -342,6 +355,100 @@
|
||||
<TextBlock Grid.Row="4" Text="No sources yet" Foreground="#555" FontSize="12"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Visibility="{Binding ShowSourcesEmptyHint, Converter={StaticResource BoolToVis}}"/>
|
||||
|
||||
<!-- ELEMENTS panel: per-element config beneath Sources -->
|
||||
<Rectangle Grid.Row="5" Height="1" Fill="#2c3a5c" Margin="0,10,0,2"/>
|
||||
<StackPanel Grid.Row="6" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<TextBlock Text="ELEMENTS" Style="{StaticResource SectionHeader}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<ScrollViewer Grid.Row="7" VerticalScrollBarVisibility="Auto" Background="Transparent">
|
||||
<StackPanel x:Name="ElementsPanel" Margin="0,4,0,0">
|
||||
<!-- Webcam border config -->
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsWebcam, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
||||
<TextBlock Text="Border Color" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
|
||||
<DockPanel Margin="0,0,0,6">
|
||||
<Button DockPanel.Dock="Right" Content="..." Width="24" Height="24"
|
||||
Click="WebcamBorderColorPicker_Click" Margin="4,0,0,0"
|
||||
ToolTip="Pick color"/>
|
||||
<TextBox Text="{Binding SelectedElement.BorderColor, UpdateSourceTrigger=PropertyChanged}"
|
||||
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
|
||||
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"
|
||||
MaxLength="7" ToolTip="#RRGGBB"/>
|
||||
</DockPanel>
|
||||
<TextBlock Text="Border Thickness" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
|
||||
<DockPanel Margin="0,0,0,6">
|
||||
<Slider DockPanel.Dock="Left" Width="120" Minimum="0" Maximum="10"
|
||||
Value="{Binding SelectedElement.BorderWidth, Mode=TwoWay}"
|
||||
VerticalAlignment="Center" TickFrequency="1" IsSnapToTickEnabled="True"/>
|
||||
<TextBlock Text="{Binding SelectedElement.BorderWidth}" Foreground="#a0a0b0" FontSize="11"
|
||||
VerticalAlignment="Center" Margin="8,0,0,0" Width="20"/>
|
||||
</DockPanel>
|
||||
<DockPanel Margin="0,4,0,0">
|
||||
<Button DockPanel.Dock="Right" Content="✓" Width="22" Height="22"
|
||||
Background="#22c55e" Foreground="White" FontSize="11" FontWeight="Bold"
|
||||
ToolTip="Applied" IsEnabled="False" Margin="4,0,0,0"/>
|
||||
<Button DockPanel.Dock="Right" Content="✕" Width="22" Height="22"
|
||||
Background="#ef4444" Foreground="White" FontSize="11" FontWeight="Bold"
|
||||
ToolTip="Revert" Click="WebcamBorderRevert_Click" Margin="4,0,0,0"/>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Countdown config -->
|
||||
<StackPanel Visibility="{Binding SelectedElement.Type, Converter={StaticResource SourceTypeToCountdownVis}, ConverterParameter=Countdown}" Margin="0,0,0,8">
|
||||
<TextBlock Text="Timer (minutes)" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
|
||||
<DockPanel Margin="0,0,0,6">
|
||||
<Slider DockPanel.Dock="Left" Width="120" Minimum="1" Maximum="60"
|
||||
Value="{Binding SelectedElement.TimerMinutes, Mode=TwoWay}"
|
||||
VerticalAlignment="Center" TickFrequency="1" IsSnapToTickEnabled="True"/>
|
||||
<TextBlock Text="{Binding SelectedElement.TimerMinutes}" Foreground="#a0a0b0" FontSize="11"
|
||||
VerticalAlignment="Center" Margin="8,0,0,0" Width="20"/>
|
||||
</DockPanel>
|
||||
<DockPanel Margin="0,4,0,0">
|
||||
<Button DockPanel.Dock="Right" Content="✓" Width="22" Height="22"
|
||||
Background="#22c55e" Foreground="White" FontSize="11" FontWeight="Bold"
|
||||
ToolTip="Applied" IsEnabled="False" Margin="4,0,0,0"/>
|
||||
<Button DockPanel.Dock="Right" Content="✕" Width="22" Height="22"
|
||||
Background="#ef4444" Foreground="White" FontSize="11" FontWeight="Bold"
|
||||
ToolTip="Revert" Click="CountdownRevert_Click" Margin="4,0,0,0"/>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Web source config -->
|
||||
<StackPanel Visibility="{Binding SelectedElement.Type, Converter={StaticResource SourceTypeToWebVis}, ConverterParameter=WebSource}" Margin="0,0,0,8">
|
||||
<TextBlock Text="URI" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
|
||||
<TextBox Text="{Binding SelectedElement.WebUri, UpdateSourceTrigger=PropertyChanged}"
|
||||
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
|
||||
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"
|
||||
ToolTip="https://example.com"/>
|
||||
<DockPanel Margin="0,4,0,0">
|
||||
<Button DockPanel.Dock="Right" Content="✓" Width="22" Height="22"
|
||||
Background="#22c55e" Foreground="White" FontSize="11" FontWeight="Bold"
|
||||
ToolTip="Applied" IsEnabled="False" Margin="4,0,0,0"/>
|
||||
<Button DockPanel.Dock="Right" Content="✕" Width="22" Height="22"
|
||||
Background="#ef4444" Foreground="White" FontSize="11" FontWeight="Bold"
|
||||
ToolTip="Revert" Click="WebRevert_Click" Margin="4,0,0,0"/>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Placeholder hint when no config available -->
|
||||
<TextBlock Text="No configurable elements" Foreground="#555" FontSize="11"
|
||||
HorizontalAlignment="Center" Margin="0,8,0,0">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding SelectedElement}" Value="{x:Null}"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</MultiDataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user