c5e3466df0
PreviewPane.xaml(.cs) takes the center preview (Row 1 Col 1): the 1920x1080
canvas (OverlayCanvas/SelectionOverlay/BrandFlashLayer/SocialBarElement),
the text pull-out drawer, and the live-controls row (TRAX / game / mic meters,
volume sliders, speaker toggles, socials button) inside the preserved
glow/background Border.
Code-behind moved into the control (drive by DataContext==MainViewModel):
preview drag/select/resize/hit-test (Preview_Mouse{Down,Move,Up},
EndPreviewDrag, HitHandle, HitElement), webcam context-menu handlers
(WebcamMenu_ChangeWebcam/SetBorderAnimation/StopBorderAnimation/
FindBorderShape/CreateBorderAnimation/AddDoubleAnimation/SetBorderColor/
HideInScene/Remove), social-bar glow (SocialBar_MouseLeftButtonDown,
SocialsButton_Mouse{Enter,Leave}, SocialGlowTick), audio controls
(VolumeSlider_*, GameVolumeSlider_*, MicSpeaker_*, GameSpeaker_*,
SetSliderValueFromClick, FindParent), and TraxButton_*.
Window keeps the left source/property/chat panel + thumbnail strip + overlay
host, and routes the selection overlay and preview hit-testing through the
control's public surface (_previewPane.UpdateSelectionOverlay(bool),
IsClickInsidePreview/Drawer, PreviewPane.IsDraggableElement). BackgroundMenu_*
stayed in the window because the left-panel source context menu uses them
(the preview's own desktop/refresh menu binds RefreshCaptureCommand instead).
Preserved the outer preview Border (background/glow/margin) that was initially
dropped in the cut — caught and restored before commit. Pruned now-unused usings
(System.Net.Http, Media.Effects, Media.Animation, Media.Imaging, Shapes,
Threading) from MainWindow.xaml.cs.
Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: ViewModels/index.md Phase 2 tracker updated in the same commit.
831 lines
61 KiB
XML
831 lines
61 KiB
XML
<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"
|
|
xmlns:models="clr-namespace:ytLive.Models"
|
|
xmlns:Helpers="clr-namespace:ytLive.Helpers"
|
|
xmlns:controls="clr-namespace:ytLive.Controls"
|
|
xmlns:notifications="clr-namespace:Notification.Wpf.Controls;assembly=Notification.Wpf"
|
|
mc:Ignorable="d"
|
|
Title="{Binding WindowTitle}" Height="1040" Width="1920"
|
|
MinWidth="1366" MinHeight="768"
|
|
Icon="/ytLive;component/Assets/llamacasty-icon.png"
|
|
Background="#1a1a2e"
|
|
WindowStartupLocation="Manual"
|
|
Closing="MainWindow_Closing"
|
|
Loaded="MainWindow_Loaded"
|
|
Activated="MainWindow_Activated"
|
|
Deactivated="MainWindow_Deactivated"
|
|
PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
|
|
ContextMenuOpening="Window_ContextMenuOpening">
|
|
|
|
<Window.DataContext>
|
|
<vm:MainViewModel/>
|
|
</Window.DataContext>
|
|
|
|
<Window.TaskbarItemInfo>
|
|
<TaskbarItemInfo x:Name="TaskbarInfo"/>
|
|
</Window.TaskbarItemInfo>
|
|
|
|
<Window.Resources>
|
|
<ResourceDictionary>
|
|
|
|
<!-- Red dot shown in the taskbar icon while live -->
|
|
<DrawingImage x:Key="LiveOverlay">
|
|
<DrawingImage.Drawing>
|
|
<DrawingGroup>
|
|
<GeometryDrawing Brush="#e94560">
|
|
<GeometryDrawing.Geometry>
|
|
<EllipseGeometry Center="8,8" RadiusX="8" RadiusY="8"/>
|
|
</GeometryDrawing.Geometry>
|
|
</GeometryDrawing>
|
|
</DrawingGroup>
|
|
</DrawingImage.Drawing>
|
|
</DrawingImage>
|
|
|
|
<!-- Eye icon: open when visible, slashed when hidden (source rows) -->
|
|
<Style x:Key="EyeIconStyle" TargetType="Path">
|
|
<Setter Property="Data" Value="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsVisible}" Value="False">
|
|
<Setter Property="Data" Value="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
|
|
<Style x:Key="EyeButton" TargetType="Button" BasedOn="{StaticResource IconButton}">
|
|
<Setter Property="ToolTip" Value="Hide Layer"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsVisible}" Value="False">
|
|
<Setter Property="ToolTip" Value="Show Layer"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</ResourceDictionary>
|
|
</Window.Resources>
|
|
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- ═══ TOP BAR: Stream Controls ═══ -->
|
|
<Border Grid.Row="0" Background="{Binding TopBarBackground}" Padding="16,10">
|
|
<controls:TopBar x:Name="TopBar"/>
|
|
</Border>
|
|
|
|
<!-- ═══ MIDDLE: Main Content ═══ -->
|
|
<controls:HealthBanner Grid.Row="1"/>
|
|
|
|
<Grid Grid.Row="2" Margin="8">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="1*" MinWidth="220" MaxWidth="360"/>
|
|
<ColumnDefinition Width="3*"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- ═══ THUMBNAIL STRIP ═══ -->
|
|
<Border Grid.Row="0" Grid.ColumnSpan="2" Background="#0d1117" CornerRadius="4" Margin="0,0,0,4"
|
|
Padding="4">
|
|
<ItemsControl ItemsSource="{Binding Scenes}">
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<UniformGrid Rows="1" Columns="5"/>
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate>
|
|
<Border CornerRadius="4" Margin="2" Padding="2"
|
|
BorderThickness="2"
|
|
BorderBrush="Transparent"
|
|
Cursor="Hand"
|
|
MouseLeftButtonDown="Thumbnail_MouseLeftButtonDown">
|
|
<Border.Style>
|
|
<Style TargetType="Border">
|
|
<Setter Property="BorderBrush" Value="#333344"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsStaged}" Value="True">
|
|
<Setter Property="BorderBrush" Value="#e94560"/>
|
|
</DataTrigger>
|
|
<DataTrigger Binding="{Binding IsLive}" Value="True">
|
|
<Setter Property="BorderBrush" Value="#22c55e"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</Border.Style>
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
<Border Grid.Row="0" CornerRadius="3"
|
|
Background="#0a0a1a" ClipToBounds="True">
|
|
<Image Source="{Binding Snapshot}"
|
|
Stretch="UniformToFill"
|
|
RenderOptions.BitmapScalingMode="LowQuality"/>
|
|
</Border>
|
|
<TextBlock Grid.Row="1" Foreground="#a0a0b0" FontSize="10"
|
|
HorizontalAlignment="Center"
|
|
Margin="0,2,0,0"
|
|
TextTrimming="CharacterEllipsis">
|
|
<Run Text="{Binding Name, Mode=OneWay}"/><Run Text=" "/><Run Text="{Binding HotkeyLabel, Mode=OneWay}" Foreground="#6a6a7a" FontWeight="SemiBold"/>
|
|
</TextBlock>
|
|
</Grid>
|
|
</Border>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
</Border>
|
|
|
|
<!-- LEFT PANEL: one panel, two states.
|
|
Offline (edit mode): LAYERS + PROPERTIES
|
|
Live/Recording: YouTube Live Chat -->
|
|
<Border Grid.Row="1" Grid.Column="0" Background="#16213e" CornerRadius="6" Padding="12">
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- Edit mode (offline): layers + properties -->
|
|
<Grid Grid.Row="0" Visibility="{Binding IsEditMode, Converter={StaticResource BoolToVis}}">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- LAYERS header + Add button -->
|
|
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,8,0,0">
|
|
<TextBlock Text="LAYERS" Style="{StaticResource SectionHeader}" VerticalAlignment="Center"/>
|
|
<Button ToolTip="Add Layer" Style="{StaticResource IconButton}" Margin="4,-4,0,0"
|
|
Click="AddSourceButton_Click">
|
|
<Button.ContextMenu>
|
|
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
|
<MenuItem Header="Webcam" Command="{Binding AddWebcamCommand}"
|
|
IsEnabled="{Binding CanAddWebcam}"
|
|
ToolTip="One webcam at a time — it's already in your stream"/>
|
|
<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 screens only"/>
|
|
<MenuItem Header="Web Resource" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.WebSource}"
|
|
ToolTip="Embedded web page — set URI in Properties panel"/>
|
|
<MenuItem Header="YouTube Chat" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.ChatBox}"
|
|
IsEnabled="{Binding CanAddYouTubeChat}"
|
|
ToolTip="One chat layer at a time — it's already in your stream"/>
|
|
</ContextMenu>
|
|
</Button.ContextMenu>
|
|
<Path Data="M12,4 L12,20 M4,12 L20,12" Stroke="#e94560" StrokeThickness="2"
|
|
Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
</StackPanel>
|
|
|
|
<Helpers:FocusPreservingListBox x:Name="SourceList" Grid.Row="1" Background="Transparent" BorderThickness="0"
|
|
ItemsSource="{Binding StagedScene.Elements}"
|
|
SelectedItem="{Binding SelectedElement, Mode=TwoWay}"
|
|
PreviewMouseLeftButtonDown="List_PreviewMouseLeftButtonDown"
|
|
PreviewMouseMove="List_PreviewMouseMove"
|
|
PreviewMouseLeftButtonUp="List_PreviewMouseLeftButtonUp"
|
|
Foreground="#e0e0e0" FontSize="13">
|
|
<Helpers:FocusPreservingListBox.ItemContainerStyle>
|
|
<Style TargetType="ListBoxItem" BasedOn="{StaticResource YtListBoxItem}">
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsVisible}" Value="False">
|
|
<Setter Property="Opacity" Value="0.45"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</Helpers:FocusPreservingListBox.ItemContainerStyle>
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate>
|
|
<Grid Margin="0,2"
|
|
Tag="{Binding DataContext.CanChangeBackground, RelativeSource={RelativeSource AncestorType=Window}}">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<Grid.ContextMenu>
|
|
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
|
<MenuItem Header="Change Capture…" Click="BackgroundMenu_ChangeCapture">
|
|
<MenuItem.Visibility>
|
|
<MultiBinding Converter="{StaticResource AllTrueToVis}">
|
|
<Binding Path="IsBackground"/>
|
|
<Binding Path="PlacementTarget.Tag" RelativeSource="{RelativeSource AncestorType={x:Type ContextMenu}}"/>
|
|
</MultiBinding>
|
|
</MenuItem.Visibility>
|
|
</MenuItem>
|
|
<MenuItem Header="Refresh Capture" Click="BackgroundMenu_RefreshCapture">
|
|
<MenuItem.Visibility>
|
|
<MultiBinding Converter="{StaticResource AllTrueToVis}">
|
|
<Binding Path="IsBackground"/>
|
|
<Binding Path="PlacementTarget.Tag" RelativeSource="{RelativeSource AncestorType={x:Type ContextMenu}}"/>
|
|
</MultiBinding>
|
|
</MenuItem.Visibility>
|
|
</MenuItem>
|
|
<Separator>
|
|
<Separator.Visibility>
|
|
<MultiBinding Converter="{StaticResource AllTrueToVis}">
|
|
<Binding Path="IsBackground"/>
|
|
<Binding Path="PlacementTarget.Tag" RelativeSource="{RelativeSource AncestorType={x:Type ContextMenu}}"/>
|
|
</MultiBinding>
|
|
</Separator.Visibility>
|
|
</Separator>
|
|
<MenuItem Header="Remove Layer" Click="SourceMenu_Remove"
|
|
Visibility="{Binding IsBackground, Converter={StaticResource InverseBoolToVis}}"/>
|
|
</ContextMenu>
|
|
</Grid.ContextMenu>
|
|
|
|
<TextBlock Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center"
|
|
Padding="4,2" TextTrimming="CharacterEllipsis">
|
|
<TextBlock.Style>
|
|
<Style TargetType="TextBlock">
|
|
<Setter Property="Visibility" Value="Visible"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsEditing}" Value="True">
|
|
<Setter Property="Visibility" Value="Collapsed"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBlock.Style>
|
|
</TextBlock>
|
|
|
|
<TextBox Grid.Column="0" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
|
|
Background="#0f3460" Foreground="#e0e0e0" BorderThickness="0"
|
|
Padding="4,2" VerticalContentAlignment="Center"
|
|
IsVisibleChanged="SourceNameBox_IsVisibleChanged"
|
|
KeyDown="SourceNameBox_KeyDown" LostFocus="SourceNameBox_LostFocus">
|
|
<TextBox.Style>
|
|
<Style TargetType="TextBox">
|
|
<Setter Property="Visibility" Value="Collapsed"/>
|
|
<Style.Triggers>
|
|
<DataTrigger Binding="{Binding IsEditing}" Value="True">
|
|
<Setter Property="Visibility" Value="Visible"/>
|
|
</DataTrigger>
|
|
</Style.Triggers>
|
|
</Style>
|
|
</TextBox.Style>
|
|
</TextBox>
|
|
|
|
<Button Grid.Column="1" ToolTip="Edit Layer Name"
|
|
Command="{Binding DataContext.EditElementCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
|
|
CommandParameter="{Binding}" Style="{StaticResource IconButton}">
|
|
<Path Data="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"
|
|
Fill="#d0d0d0" Width="13" Height="13" Stretch="Uniform"/>
|
|
</Button>
|
|
|
|
<Button Grid.Column="2" Style="{StaticResource EyeButton}"
|
|
Command="{Binding DataContext.ToggleElementVisibilityCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
|
|
CommandParameter="{Binding}">
|
|
<Path Style="{StaticResource EyeIconStyle}" Fill="#d0d0d0"
|
|
Width="13" Height="13" Stretch="Uniform"/>
|
|
</Button>
|
|
|
|
<Button Grid.Column="3" ToolTip="Remove Layer"
|
|
Command="{Binding DataContext.RemoveSourceCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
|
|
CommandParameter="{Binding}" Style="{StaticResource IconButton}"
|
|
Visibility="{Binding IsBackground, Converter={StaticResource HiddenBoolToVis}}">
|
|
<Path Data="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"
|
|
Fill="#d0d0d0" Width="13" Height="13" Stretch="Uniform"/>
|
|
</Button>
|
|
</Grid>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</Helpers:FocusPreservingListBox>
|
|
|
|
<TextBlock Grid.Row="2" Text="No layers yet" Foreground="#555" FontSize="12"
|
|
HorizontalAlignment="Center" VerticalAlignment="Center"
|
|
Visibility="{Binding ShowSourcesEmptyHint, Converter={StaticResource BoolToVis}}"/>
|
|
|
|
<!-- ELEMENTS panel: per-element config beneath Sources.
|
|
Collapses entirely when no element is selected. -->
|
|
<Rectangle Grid.Row="3" Height="1" Fill="#2c3a5c" Margin="0,10,0,2"
|
|
Visibility="{Binding SelectedElement, Converter={StaticResource NotNullToVis}}"/>
|
|
<StackPanel Grid.Row="4" Orientation="Horizontal" Margin="0,8,0,0"
|
|
Visibility="{Binding SelectedElement, Converter={StaticResource NotNullToVis}}">
|
|
<TextBlock Text="PROPERTIES" Style="{StaticResource SectionHeader}" VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<ScrollViewer x:Name="ElementsScrollViewer" Grid.Row="5" VerticalScrollBarVisibility="Auto" Background="Transparent"
|
|
Visibility="{Binding SelectedElement, Converter={StaticResource NotNullToVis}}">
|
|
<StackPanel x:Name="ElementsPanel" Margin="0,4,0,0">
|
|
<!-- Opacity + mirror/shape (draggable elements: image, webcam) -->
|
|
<StackPanel Visibility="{Binding SelectedElement.IsDraggable, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
|
<StackPanel Visibility="{Binding SelectedElement.IsChatBox, Converter={StaticResource InverseBoolToVis}}">
|
|
<TextBlock Text="Opacity" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
|
|
<DockPanel Margin="0,0,0,6">
|
|
<TextBlock x:Name="OpacityValueText" Text="100%" Foreground="#a0a0b0" FontSize="11"
|
|
DockPanel.Dock="Right" VerticalAlignment="Center" Margin="8,0,0,0" Width="32"/>
|
|
<Slider x:Name="OpacitySlider" Width="120" Minimum="0" Maximum="1"
|
|
Value="{Binding SelectedElement.Opacity, Mode=TwoWay}"
|
|
ValueChanged="OpacitySlider_ValueChanged" VerticalAlignment="Center"/>
|
|
</DockPanel>
|
|
</StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,4"
|
|
Visibility="{Binding IsWebcamSelected, Converter={StaticResource BoolToVis}}">
|
|
<Button Content="{Binding SelectedElement.MirrorButtonText}"
|
|
Style="{StaticResource YtButtonSecondary}" Padding="10,4"
|
|
Click="MirrorButton_Click"/>
|
|
<Button Content="{Binding SelectedElement.ShapeButtonText}"
|
|
Style="{StaticResource YtButtonSecondary}" Padding="10,4"
|
|
Margin="8,0,0,0" Click="ShapeButton_Click"/>
|
|
</StackPanel>
|
|
<TextBlock Text="Drag to move · drag the corner dot to resize"
|
|
Foreground="#a0a0b0" FontSize="10" Margin="0,2,0,0"/>
|
|
</StackPanel>
|
|
|
|
<!-- 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">
|
|
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
|
Width="22" Height="22" Margin="4,0,0,0"
|
|
Click="WebcamBorderAccept_Click">
|
|
<Path Data="M4,9 L8,14 L16,4" Stroke="#22c55e" StrokeThickness="2"
|
|
Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
|
Width="22" Height="22" ToolTip="Revert"
|
|
Click="WebcamBorderRevert_Click" Margin="4,0,0,0">
|
|
<Path Data="M5,5 L15,15 M15,5 L5,15" Stroke="#e94560" StrokeThickness="2"
|
|
Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
<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>
|
|
</StackPanel>
|
|
|
|
<!-- Countdown config -->
|
|
<StackPanel Visibility="{Binding SelectedElement.IsCountdown, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
|
<TextBlock Text="Timer (minutes)" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
|
|
<DockPanel Margin="0,0,0,6">
|
|
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
|
Width="22" Height="22" Margin="4,0,0,0"
|
|
Click="CountdownAccept_Click">
|
|
<Path Data="M4,9 L8,14 L16,4" Stroke="#22c55e" StrokeThickness="2"
|
|
Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
|
Width="22" Height="22" ToolTip="Revert"
|
|
Click="CountdownRevert_Click" Margin="4,0,0,0">
|
|
<Path Data="M5,5 L15,15 M15,5 L5,15" Stroke="#e94560" StrokeThickness="2"
|
|
Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
<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>
|
|
</StackPanel>
|
|
|
|
<!-- Web source config -->
|
|
<StackPanel Visibility="{Binding SelectedElement.IsWebSource, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
|
<TextBlock Text="Geometry" Foreground="#a0a0b0" FontSize="11" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="X" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="16"/>
|
|
<TextBox Text="{Binding SelectedElement.X, UpdateSourceTrigger=PropertyChanged, StringFormat=F0}"
|
|
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"/>
|
|
<TextBlock DockPanel.Dock="Left" Text=" Y" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="20" Margin="8,0,0,0"/>
|
|
<TextBox Text="{Binding SelectedElement.Y, UpdateSourceTrigger=PropertyChanged, StringFormat=F0}"
|
|
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"/>
|
|
</DockPanel>
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="W" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="16"/>
|
|
<TextBox Text="{Binding SelectedElement.Width, UpdateSourceTrigger=PropertyChanged, StringFormat=F0}"
|
|
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"/>
|
|
<TextBlock DockPanel.Dock="Left" Text=" H" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="20" Margin="8,0,0,0"/>
|
|
<TextBox Text="{Binding SelectedElement.Height, UpdateSourceTrigger=PropertyChanged, StringFormat=F0}"
|
|
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"/>
|
|
</DockPanel>
|
|
<TextBlock Text="URI" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
|
|
<DockPanel>
|
|
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
|
Width="22" Height="22" Margin="4,0,0,0" IsTabStop="False"
|
|
Click="WebAccept_Click">
|
|
<Path Data="M4,9 L8,14 L16,4" Stroke="#22c55e" StrokeThickness="2"
|
|
Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
|
|
Width="22" Height="22" ToolTip="Revert" IsTabStop="False"
|
|
Click="WebRevert_Click" Margin="4,0,0,0">
|
|
<Path Data="M5,5 L15,15 M15,5 L5,15" Stroke="#e94560" StrokeThickness="2"
|
|
Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
<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>
|
|
</StackPanel>
|
|
|
|
<!-- Chat box config -->
|
|
<StackPanel Visibility="{Binding SelectedElement.IsChatBox, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
|
<TextBlock Text="Chat Overlay" Foreground="#a0a0b0" FontSize="11" FontWeight="SemiBold" Margin="0,0,0,6"/>
|
|
|
|
<!-- Font Size -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Font Size" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<Slider x:Name="ChatFontSizeSlider" Width="120" Minimum="8" Maximum="72" TickFrequency="2" IsSnapToTickEnabled="True"
|
|
Value="{Binding SelectedElement.ChatFontSize, Mode=TwoWay}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock DockPanel.Dock="Right" Text="{Binding SelectedElement.ChatFontSize, StringFormat={}{0:0}}" Foreground="#e0e0e0" FontSize="11" Margin="6,0,0,0" VerticalAlignment="Center" Width="24"/>
|
|
</DockPanel>
|
|
|
|
<!-- Font Family -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Font" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<ComboBox SelectedValue="{Binding SelectedElement.ChatFontFamily, Mode=TwoWay}"
|
|
SelectedValuePath="Content"
|
|
Background="#0f3460" Foreground="#e0e0e0" FontSize="11"
|
|
Width="140" VerticalAlignment="Center">
|
|
<ComboBoxItem Content="Segoe UI"/>
|
|
<ComboBoxItem Content="Arial"/>
|
|
<ComboBoxItem Content="Consolas"/>
|
|
<ComboBoxItem Content="Courier New"/>
|
|
<ComboBoxItem Content="Comic Sans MS"/>
|
|
<ComboBoxItem Content="Mouse Memoirs"/>
|
|
</ComboBox>
|
|
</DockPanel>
|
|
|
|
<!-- Font Color -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Font Color" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<TextBox Text="{Binding SelectedElement.ChatFontColor, UpdateSourceTrigger=PropertyChanged}"
|
|
Background="#0f3460" Foreground="#e0e0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="11" Width="80"/>
|
|
</DockPanel>
|
|
|
|
<!-- Member Color -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Member" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<TextBox Text="{Binding SelectedElement.ChatMemberColor, UpdateSourceTrigger=PropertyChanged}"
|
|
Background="#0f3460" Foreground="#e0e0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="11" Width="80"/>
|
|
</DockPanel>
|
|
|
|
<!-- Super Chat Color -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Super Chat" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<TextBox Text="{Binding SelectedElement.ChatSuperChatColor, UpdateSourceTrigger=PropertyChanged}"
|
|
Background="#0f3460" Foreground="#e0e0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="11" Width="80"/>
|
|
</DockPanel>
|
|
|
|
<!-- Max Messages -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Max Msgs" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<Slider x:Name="ChatMaxMsgsSlider" Width="120" Minimum="1" Maximum="20" TickFrequency="1" IsSnapToTickEnabled="True"
|
|
Value="{Binding SelectedElement.ChatMaxMessages, Mode=TwoWay}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock DockPanel.Dock="Right" Text="{Binding SelectedElement.ChatMaxMessages}" Foreground="#e0e0e0" FontSize="11" Margin="6,0,0,0" VerticalAlignment="Center" Width="24"/>
|
|
</DockPanel>
|
|
|
|
<!-- Background Color -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Background" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<TextBox Text="{Binding SelectedElement.ChatBackgroundColor, UpdateSourceTrigger=PropertyChanged}"
|
|
Background="#0f3460" Foreground="#e0e0e0" BorderThickness="1"
|
|
BorderBrush="#2c3a5c" Padding="4,2" FontSize="11" Width="80"/>
|
|
</DockPanel>
|
|
|
|
<!-- Background Opacity -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Bg Opacity" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<Slider x:Name="ChatBgOpacitySlider" Width="120" Minimum="0" Maximum="1"
|
|
Value="{Binding SelectedElement.ChatBackgroundOpacity, Mode=TwoWay}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock DockPanel.Dock="Right" Text="{Binding SelectedElement.ChatBackgroundOpacity, StringFormat={}{0:0%}}" Foreground="#e0e0e0" FontSize="11" Margin="6,0,0,0" VerticalAlignment="Center" Width="32"/>
|
|
</DockPanel>
|
|
|
|
<!-- Fade After (seconds) -->
|
|
<DockPanel Margin="0,0,0,4">
|
|
<TextBlock DockPanel.Dock="Left" Text="Fade After" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center" Width="70"/>
|
|
<Slider x:Name="ChatFadeSlider" Width="120" Minimum="0" Maximum="60" TickFrequency="5" IsSnapToTickEnabled="True"
|
|
Value="{Binding SelectedElement.ChatFadeSeconds, Mode=TwoWay}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock DockPanel.Dock="Right" Text="{Binding SelectedElement.ChatFadeSeconds, StringFormat='{}{0}s'}" Foreground="#e0e0e0" FontSize="11" Margin="6,0,0,0" VerticalAlignment="Center" Width="28"/>
|
|
</DockPanel>
|
|
|
|
<!-- Toggles -->
|
|
<CheckBox Content="Show timestamps" Foreground="#a0a0b0" FontSize="11" Margin="0,4,0,2"
|
|
IsChecked="{Binding SelectedElement.ChatShowTimestamps, Mode=TwoWay}"/>
|
|
<CheckBox Content="Show badges" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"
|
|
IsChecked="{Binding SelectedElement.ChatShowBadges, Mode=TwoWay}"/>
|
|
</StackPanel>
|
|
|
|
<!-- Background properties -->
|
|
<StackPanel Margin="0,8,0,0"
|
|
Visibility="{Binding SelectedElement.IsBackground, Converter={StaticResource BoolToVis}}">
|
|
<TextBlock Text="Background" Style="{StaticResource SubHeader}"/>
|
|
<StackPanel Margin="4,0,0,0">
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<TextBlock Text="Use default background:" Foreground="#a0a0b0" FontSize="11" VerticalAlignment="Center"/>
|
|
<ToggleButton Style="{StaticResource PillToggle}"
|
|
IsChecked="{Binding SelectedElement.UseDefaultBackground, Mode=TwoWay}"
|
|
Margin="8,0,0,0"/>
|
|
</StackPanel>
|
|
<Grid Margin="0,0,0,4"
|
|
Visibility="{Binding SelectedElement.UseDefaultBackground, Converter={StaticResource InverseBoolToVis}}">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
<TextBox Grid.Column="0" Text="{Binding SelectedElement.CustomBackgroundPath, Mode=OneWay}"
|
|
IsReadOnly="True" Background="#0f3460" Foreground="#a0a0b0"
|
|
FontSize="11" VerticalAlignment="Center"/>
|
|
<Button Grid.Column="1" Content="Browse…" Command="{Binding BrowseBackgroundCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" Margin="4,0,0,0" Padding="8,2"/>
|
|
</Grid>
|
|
<TextBlock Text="{Binding BackgroundSizeMismatchText}"
|
|
Foreground="#ef4444" FontSize="11" TextWrapping="Wrap"
|
|
Margin="0,4,0,0"
|
|
Visibility="{Binding BackgroundSizeMismatch, Converter={StaticResource BoolToVis}}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</Grid>
|
|
|
|
<!-- Live mode: YouTube Live Chat (entire left panel replaced) -->
|
|
<Grid Grid.Row="0" Visibility="{Binding IsEditMode, Converter={StaticResource InverseBoolToVis}}">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="LIVE CHAT" Style="{StaticResource SectionHeader}"/>
|
|
|
|
<!-- Inactive overlay (shown when NOT live) -->
|
|
<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center"
|
|
Visibility="{Binding ShowChatInactiveMessage, Converter={StaticResource BoolToVis}}">
|
|
<TextBlock Text="Chat is inactive" Foreground="#a0a0b0" FontSize="13"
|
|
HorizontalAlignment="Center" Margin="0,0,0,4"/>
|
|
<TextBlock Text="Chat becomes active once LlamaCasty is connected and streaming on YouTube."
|
|
Foreground="#666" FontSize="11" TextWrapping="Wrap"
|
|
HorizontalAlignment="Center" TextAlignment="Center" MaxWidth="240"/>
|
|
</StackPanel>
|
|
|
|
<!-- Message feed (shown when live) -->
|
|
<ListBox Grid.Row="1" Background="Transparent" BorderThickness="0"
|
|
ItemsSource="{Binding ChatMessages}"
|
|
ItemContainerStyle="{StaticResource YtListBoxItem}"
|
|
Visibility="{Binding ShowChatInactiveMessage, Converter={StaticResource InverseBoolToVis}}"
|
|
x:Name="ChatListBox">
|
|
<ListBox.ItemTemplate><DataTemplate>
|
|
<Border x:Name="MessageBorder" Padding="6,4" CornerRadius="4">
|
|
<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" Margin="0,0,0,2">
|
|
<TextBlock Text="⭐" FontSize="10" Margin="0,0,4,0"
|
|
VerticalAlignment="Center"
|
|
Visibility="{Binding IsMember, Converter={StaticResource BoolToVis}}"/>
|
|
<TextBlock Text="{Binding AuthorName}" Foreground="#e94560"
|
|
FontWeight="Bold" FontSize="12" VerticalAlignment="Center"/>
|
|
<TextBlock Text="{Binding SuperChatAmount, StringFormat=${0:F2}}"
|
|
Foreground="#eab308" FontWeight="Bold" FontSize="12"
|
|
Margin="8,0,0,0" VerticalAlignment="Center"
|
|
Visibility="{Binding IsSuperChat, Converter={StaticResource BoolToVis}}"/>
|
|
<TextBlock Text="{Binding SuperChatCurrency}" Foreground="#eab308"
|
|
FontSize="11" Margin="2,0,0,0" VerticalAlignment="Center"
|
|
Visibility="{Binding IsSuperChat, Converter={StaticResource BoolToVis}}"/>
|
|
</StackPanel>
|
|
<TextBlock Text="{Binding Message}" Foreground="#e0e0e0"
|
|
TextWrapping="Wrap" Margin="0,2,0,0"/>
|
|
</StackPanel>
|
|
</Border>
|
|
</DataTemplate></ListBox.ItemTemplate>
|
|
</ListBox>
|
|
</Grid>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- CENTER: Preview Area -->
|
|
<controls:PreviewPane x:Name="PreviewPane" Grid.Row="1" Grid.Column="1"/>
|
|
</Grid>
|
|
|
|
|
|
<controls:BottomBar Grid.Row="3"/>
|
|
<!-- ═══ OVERLAY: Settings / Bug / Feature / About ═══ -->
|
|
<Grid Grid.RowSpan="3"
|
|
Visibility="{Binding IsAnyOverlayOpen, Converter={StaticResource BoolToVis}}">
|
|
<Button Background="#99000000" BorderThickness="0" Cursor="Hand"
|
|
Command="{Binding CloseOverlayCommand}">
|
|
<Button.Template>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border Background="{TemplateBinding Background}"/>
|
|
</ControlTemplate>
|
|
</Button.Template>
|
|
</Button>
|
|
|
|
<Border Background="#0A0C1A" CornerRadius="8" Width="650" MaxHeight="700"
|
|
VerticalAlignment="Center" HorizontalAlignment="Center"
|
|
Padding="28" BorderBrush="#333" BorderThickness="1">
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- Header -->
|
|
<Grid Grid.Row="0">
|
|
<TextBlock Text="{Binding OverlayTitle}" FontSize="18" FontWeight="Bold"
|
|
Foreground="#e0e0e0" VerticalAlignment="Center"/>
|
|
<Button HorizontalAlignment="Right" ToolTip="Close" Style="{StaticResource IconButton}"
|
|
Command="{Binding CloseOverlayCommand}">
|
|
<Path Data="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"
|
|
Fill="#d0d0d0" Width="14" Height="14" Stretch="Uniform"/>
|
|
</Button>
|
|
</Grid>
|
|
|
|
<!-- App Settings: broadcast fields live in the preview's
|
|
Text pull-out now — this panel keeps app-level prefs only.
|
|
(Currently empty; the overlay shell stays for future use.) -->
|
|
<StackPanel Grid.Row="1" Margin="0,16,0,0"
|
|
Visibility="{Binding IsSettingsOpen, Converter={StaticResource BoolToVis}}">
|
|
<TextBlock Text="Default Location for Recordings" Style="{StaticResource YtLabel}" Margin="0,0,0,4"/>
|
|
<TextBox Style="{StaticResource YtTextBox}"
|
|
Text="{Binding RecordFolderDisplay, Mode=OneWay}"
|
|
IsReadOnly="True" Margin="0,0,0,12" Foreground="#a0a0b0"/>
|
|
<StackPanel Orientation="Horizontal">
|
|
<Button Content="Browse…" Command="{Binding ChooseRecordFolderCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" Margin="0,0,8,0"/>
|
|
<Button Content="Use Downloads" Command="{Binding ResetRecordFolderCommand}"
|
|
Style="{StaticResource YtButtonSecondary}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Report Bug -->
|
|
<StackPanel Grid.Row="1" Margin="0,16,0,0"
|
|
Visibility="{Binding IsBugOpen, Converter={StaticResource BoolToVis}}">
|
|
<TextBlock Text="What went wrong?" Style="{StaticResource YtLabel}" Margin="0,0,0,4"/>
|
|
<TextBox Style="{StaticResource YtTextBox}" Height="110" AcceptsReturn="True" TextWrapping="Wrap"
|
|
Margin="0,0,0,12"
|
|
Text="{Binding BugReportText, UpdateSourceTrigger=PropertyChanged}"
|
|
VerticalScrollBarVisibility="Auto"/>
|
|
|
|
<TextBlock Text="Email (optional)" Style="{StaticResource YtLabel}" Margin="0,0,0,4"/>
|
|
<TextBox Style="{StaticResource YtTextBox}" Margin="0,0,0,12"
|
|
Text="{Binding BugReportEmail, UpdateSourceTrigger=PropertyChanged}"/>
|
|
|
|
<TextBlock Text="Opens a pre-filled email to the LlamaCasty team." Style="{StaticResource YtLabel}"/>
|
|
<Button Content="Send Report" Command="{Binding SubmitBugCommand}"
|
|
Style="{StaticResource YtButton}" HorizontalAlignment="Right" Margin="0,16,0,0"/>
|
|
</StackPanel>
|
|
|
|
<!-- Feature Request -->
|
|
<StackPanel Grid.Row="1" Margin="0,16,0,0"
|
|
Visibility="{Binding IsFeatureOpen, Converter={StaticResource BoolToVis}}">
|
|
<TextBlock Text="What would you like to see?" Style="{StaticResource YtLabel}" Margin="0,0,0,4"/>
|
|
<TextBox Style="{StaticResource YtTextBox}" Height="110" AcceptsReturn="True" TextWrapping="Wrap"
|
|
Margin="0,0,0,12"
|
|
Text="{Binding FeatureRequestText, UpdateSourceTrigger=PropertyChanged}"
|
|
VerticalScrollBarVisibility="Auto"/>
|
|
|
|
<TextBlock Text="Email (optional)" Style="{StaticResource YtLabel}" Margin="0,0,0,4"/>
|
|
<TextBox Style="{StaticResource YtTextBox}" Margin="0,0,0,12"
|
|
Text="{Binding FeatureRequestEmail, UpdateSourceTrigger=PropertyChanged}"/>
|
|
|
|
<TextBlock Text="Opens a pre-filled email to the LlamaCasty team." Style="{StaticResource YtLabel}"/>
|
|
<Button Content="Send Request" Command="{Binding SubmitFeatureCommand}"
|
|
Style="{StaticResource YtButton}" HorizontalAlignment="Right" Margin="0,16,0,0"/>
|
|
</StackPanel>
|
|
|
|
<!-- About -->
|
|
<Grid Grid.Row="1" Margin="0,16,0,0"
|
|
Background="#171928"
|
|
Visibility="{Binding IsAboutOpen, Converter={StaticResource BoolToVis}}">
|
|
|
|
<!-- Hub view -->
|
|
<StackPanel Visibility="{Binding IsHubVisible, Converter={StaticResource BoolToVis}}">
|
|
<Image Source="/ytLive;component/Assets/llamacasty-logo.jpg" Height="125" Stretch="Uniform"
|
|
HorizontalAlignment="Center" Margin="0,0,0,12"/>
|
|
<TextBlock Text="{Binding AppVersionLabel}" Foreground="#a0a0b0" FontSize="12"
|
|
HorizontalAlignment="Center" Margin="0,4,0,0"/>
|
|
<TextBlock Text="Live streaming for YouTube — simple enough that even the most right-brained person can intuit it."
|
|
Foreground="#a0a0b0" FontSize="13" TextWrapping="Wrap" MaxWidth="380"
|
|
TextAlignment="Center" Margin="0,16,0,0"/>
|
|
<TextBlock Text="Free forever — live streams carry a brief "made with LlamaCasty!" flash. A subscription removes it and adds alerts."
|
|
Foreground="#888" FontSize="12" TextWrapping="Wrap" MaxWidth="380"
|
|
TextAlignment="Center" Margin="0,12,0,0"/>
|
|
<TextBlock Text="Made by gramps · llama chile shop" Foreground="#a0a0b0" FontSize="12"
|
|
HorizontalAlignment="Center" Margin="0,16,0,8"/>
|
|
|
|
<!-- Creator hub links -->
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,0,0,8">
|
|
<Button Content="llama chile shop on YouTube" Command="{Binding OpenChannelCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" Margin="0,0,8,0"/>
|
|
<Button Content="Mastodon" Command="{Binding OpenMastodonCommand}"
|
|
Style="{StaticResource YtButtonSecondary}"/>
|
|
</StackPanel>
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
|
<Button Content="Buy me a coffee" Command="{Binding OpenCoffeeCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" Margin="0,0,8,0"/>
|
|
<Button Content="Unlock Premium" Command="{Binding OpenPremiumCommand}"
|
|
Style="{StaticResource YtButtonSecondary}"
|
|
IsEnabled="{Binding IsPremiumAvailable}"
|
|
ToolTip="Open the LlamaCasty subscription page"/>
|
|
<Button Content="Enter License Key" Command="{Binding OpenLicenseEntryCommand}"
|
|
Style="{StaticResource YtButtonSecondary}"
|
|
ToolTip="Activate a license key to remove the watermark"/>
|
|
</StackPanel>
|
|
|
|
<Button Content="Licenses & legal" Command="{Binding OpenLicensesCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" HorizontalAlignment="Center"
|
|
Margin="0,16,0,0"/>
|
|
</StackPanel>
|
|
|
|
<!-- Licensing/legal panel -->
|
|
<StackPanel Visibility="{Binding IsLicensesOpen, Converter={StaticResource BoolToVis}}">
|
|
<TextBlock Text="Third-party notices & license texts" FontSize="15" FontWeight="Bold"
|
|
Foreground="#e0e0e0" Margin="0,0,0,8"/>
|
|
<Border Background="#10101e" CornerRadius="4" Padding="10" MaxHeight="360"
|
|
BorderBrush="#333" BorderThickness="1">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
|
<TextBlock Text="{Binding LicensesText}" Foreground="#b8b8c8" FontSize="11"
|
|
FontFamily="Consolas" TextWrapping="Wrap"/>
|
|
</ScrollViewer>
|
|
</Border>
|
|
<Button Content="← Back to About" Style="{StaticResource YtButtonSecondary}"
|
|
HorizontalAlignment="Left" Margin="0,12,0,0"
|
|
Click="BackToAbout_Click"/>
|
|
</StackPanel>
|
|
|
|
<!-- License key entry panel -->
|
|
<StackPanel Visibility="{Binding IsLicenseEntryOpen, Converter={StaticResource BoolToVis}}">
|
|
<TextBlock Text="Activate LlamaCasty Premium" FontSize="15" FontWeight="Bold"
|
|
Foreground="#e0e0e0" Margin="0,0,0,8"/>
|
|
<TextBlock Text="Enter your license key to remove the branding watermark."
|
|
Foreground="#a0a0b0" FontSize="12" TextWrapping="Wrap" Margin="0,0,0,12"/>
|
|
<TextBlock Text="License Key" Style="{StaticResource YtLabel}" Margin="0,0,0,4"/>
|
|
<TextBox Style="{StaticResource YtTextBox}" Margin="0,0,0,12"
|
|
Text="{Binding LicenseKey, UpdateSourceTrigger=PropertyChanged}"
|
|
MaxLength="100"/>
|
|
<Button Content="Activate" Command="{Binding ActivateLicenseCommand}"
|
|
Style="{StaticResource YtButton}" HorizontalAlignment="Right"
|
|
Margin="0,0,0,8"/>
|
|
<TextBlock Text="{Binding LicenseMessage}" Foreground="#a0a0b0" FontSize="12"
|
|
TextWrapping="Wrap" Margin="0,0,0,8"/>
|
|
<Button Content="← Back to About" Style="{StaticResource YtButtonSecondary}"
|
|
HorizontalAlignment="Left" Margin="0,8,0,0"
|
|
Click="BackToAbout_Click"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Grid>
|
|
</Border>
|
|
</Grid>
|
|
|
|
<!-- ═══ WEB SOURCE HOST: hidden panel for WebView2 controls ═══ -->
|
|
<Canvas x:Name="WebViewHostPanel" Grid.RowSpan="4"
|
|
Opacity="0" IsHitTestVisible="False" Background="Transparent"/>
|
|
|
|
<!-- ═══ TOASTS: non-blocking notifications (bottom-right, above footer) ═══ -->
|
|
<notifications:NotificationArea x:Name="ToastArea"
|
|
Grid.RowSpan="4"
|
|
Position="BottomRight" MaxItems="4"
|
|
Margin="0,0,12,96"/>
|
|
</Grid>
|
|
</Window>
|