Initial scaffold: ytLive C# WPF project
- MVVM architecture (Models, ViewModels, Views, Services, Helpers) - Models: Scene, Source, StreamConfig, StreamHealth, YouTubeChannel, ChatMessage - Services: YouTubeAuthService (OAuth2), YouTubeStreamService (broadcasts/stream health), YouTubeChatService (live chat polling) - ViewModels: MainViewModel with scene management, stream controls, chat - MainWindow with dark theme: scene/source panel, preview area, chat panel, status bar - Version roadmap: v0.1 (scenes, RTMP, OAuth2, chat, health) -> 1.0
This commit is contained in:
+242
@@ -0,0 +1,242 @@
|
||||
<Window x:Class="ytLive.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:ytLive.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
Title="ytLive" Height="720" Width="1280"
|
||||
Background="#1a1a2e"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
|
||||
<Window.DataContext>
|
||||
<vm:MainViewModel/>
|
||||
</Window.DataContext>
|
||||
|
||||
<Window.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<!-- Base button style -->
|
||||
<Style x:Key="YtButton" TargetType="Button">
|
||||
<Setter Property="Background" Value="#e94560"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Padding" Value="16,8"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
CornerRadius="4"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="YtButtonSecondary" TargetType="Button" BasedOn="{StaticResource YtButton}">
|
||||
<Setter Property="Background" Value="#16213e"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="YtTextBox" TargetType="TextBox">
|
||||
<Setter Property="Background" Value="#0f3460"/>
|
||||
<Setter Property="Foreground" Value="#e0e0e0"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Padding" Value="8,6"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="CaretBrush" Value="White"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="YtLabel" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#a0a0b0"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SectionHeader" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#e0e0e0"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Margin" Value="0,0,0,8"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- ═══ TOP BAR: Stream Controls ═══ -->
|
||||
<Border Grid.Row="0" Background="#16213e" Padding="16,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Logo / Brand -->
|
||||
<TextBlock Grid.Column="0" Text="ytLive"
|
||||
Foreground="#e94560" FontSize="22" FontWeight="Bold"
|
||||
VerticalAlignment="Center" Margin="0,0,24,0"/>
|
||||
|
||||
<!-- Stream Title -->
|
||||
<TextBox Grid.Column="1" Style="{StaticResource YtTextBox}"
|
||||
Text="{Binding StreamTitle, UpdateSourceTrigger=PropertyChanged}"
|
||||
Width="400" HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<!-- Stream Status -->
|
||||
<Border Grid.Column="2" Background="#0f3460" CornerRadius="4"
|
||||
Padding="12,6" Margin="16,0" VerticalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Ellipse Width="10" Height="10" Margin="0,0,8,0">
|
||||
<Ellipse.Style>
|
||||
<Style TargetType="Ellipse">
|
||||
<Setter Property="Fill" Value="#555"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding StreamStatus}" Value="Streaming">
|
||||
<Setter Property="Fill" Value="#00ff00"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding StreamStatus}" Value="Connecting">
|
||||
<Setter Property="Fill" Value="#ffaa00"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding StreamStatus}" Value="Error">
|
||||
<Setter Property="Fill" Value="#ff0000"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Ellipse.Style>
|
||||
</Ellipse>
|
||||
<TextBlock Text="{Binding StatusDisplay}" Foreground="White"
|
||||
FontSize="13" FontWeight="SemiBold" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Stream Controls -->
|
||||
<StackPanel Grid.Column="3" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Button Content="▶ GO LIVE" Style="{StaticResource YtButton}"
|
||||
Command="{Binding StartStreamCommand}"
|
||||
Visibility="{Binding StreamStatus, Converter={StaticResource BoolToVis},
|
||||
ConverterParameter=Offline}"/>
|
||||
<Button Content="■ STOP" Style="{StaticResource YtButton}"
|
||||
Background="#333" Command="{Binding StopStreamCommand}"/>
|
||||
<Button Content="YouTube" Style="{StaticResource YtButtonSecondary}"
|
||||
Command="{Binding ConnectYouTubeCommand}" Margin="8,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ═══ MIDDLE: Main Content ═══ -->
|
||||
<Grid Grid.Row="1" Margin="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="220"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="300"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- LEFT PANEL: Scenes & Sources -->
|
||||
<Border Grid.Column="0" Background="#16213e" CornerRadius="6" Padding="12">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Scenes -->
|
||||
<TextBlock Grid.Row="0" Text="SCENES" Style="{StaticResource SectionHeader}"/>
|
||||
|
||||
<ListBox Grid.Row="1" Background="Transparent" BorderThickness="0"
|
||||
ItemsSource="{Binding Scenes}"
|
||||
SelectedItem="{Binding ActiveScene}"
|
||||
Foreground="#e0e0e0" FontSize="13">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}" Padding="4,4"/>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<Button Content="+" Style="{StaticResource YtButtonSecondary}"
|
||||
Command="{Binding AddSceneCommand}" Padding="8,4" Margin="0,0,4,0"/>
|
||||
<Button Content="−" Style="{StaticResource YtButtonSecondary}"
|
||||
Command="{Binding RemoveSceneCommand}" Padding="8,4"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Sources (for active scene) -->
|
||||
<TextBlock Grid.Row="3" Text="SOURCES" Style="{StaticResource SectionHeader}" Margin="0,12,0,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- CENTER: Preview Area -->
|
||||
<Border Grid.Column="1" Background="#0a0a1a" CornerRadius="6" Margin="8,0">
|
||||
<Grid>
|
||||
<TextBlock Text="Preview" Foreground="#333" FontSize="24"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<!-- TODO: D3DImage or MediaElement for video preview -->
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- RIGHT PANEL: Chat -->
|
||||
<Border Grid.Column="2" Background="#16213e" CornerRadius="6" Padding="12">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Text="LIVE CHAT" Style="{StaticResource SectionHeader}"/>
|
||||
|
||||
<ListBox Grid.Row="1" Background="Transparent" BorderThickness="0"
|
||||
ItemsSource="{Binding ChatMessages}"
|
||||
Foreground="#e0e0e0" FontSize="12">
|
||||
<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>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- ═══ BOTTOM BAR: Stream Health ═══ -->
|
||||
<Border Grid.Row="2" Background="#0f3460" Padding="16,6">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="Bitrate:" Style="{StaticResource YtLabel}" Margin="0,0,4,0"/>
|
||||
<TextBlock Text="{Binding CurrentHealth.CurrentBitrate}" Style="{StaticResource YtLabel}"
|
||||
Foreground="White" Margin="0,0,20,0"/>
|
||||
|
||||
<TextBlock Text="FPS:" Style="{StaticResource YtLabel}" Margin="0,0,4,0"/>
|
||||
<TextBlock Text="{Binding CurrentHealth.FPS}" Style="{StaticResource YtLabel}"
|
||||
Foreground="White" Margin="0,0,20,0"/>
|
||||
|
||||
<TextBlock Text="Dropped:" Style="{StaticResource YtLabel}" Margin="0,0,4,0"/>
|
||||
<TextBlock Text="{Binding CurrentHealth.DroppedFrames}" Style="{StaticResource YtLabel}"
|
||||
Foreground="White" Margin="0,0,20,0"/>
|
||||
|
||||
<TextBlock Text="Duration:" Style="{StaticResource YtLabel}" Margin="0,0,4,0"/>
|
||||
<TextBlock Text="{Binding CurrentHealth.StreamDuration}" Style="{StaticResource YtLabel}"
|
||||
Foreground="White"/>
|
||||
|
||||
<TextBlock Text="{Binding CurrentHealth.HealthMessage}" Style="{StaticResource YtLabel}"
|
||||
Foreground="#e94560" Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
Reference in New Issue
Block a user