Slice 4. 607 green, 0 warnings. Clips remain **off by default** and, while off, the ring is never constructed — so no reader thread and no encoder output exist until someone asks for the feature. - **F10** (`HotkeyId.SaveClip`, default F10, remappable in the hotkey dialog) snapshots the ring, writes the file, prunes to the retention count and toasts the name. Empty ring → "nothing to clip yet" instead of a zero-byte file; clips off → says so and points at Settings. - **Settings**: Enable, length (10 or 15, default 10), keep (3/4/5, default 3). Persisted in the layout store and **coerced on load** — a bad stored value falls back to a legal one, so the ring can never be sized for a length the UI cannot show. - The ring is sized from length × tier bitrate × 1.25 and rebuilt if either changes; it is created at session start and dropped at stop, so memory is only spent while a show is running. - The drawer states the boundary in the creator's terms: "A capture, not an editor: for trimming, captions or a library, use a video editor." Still to come: the replay layer itself (play once then hide in Live, loop the kept clips elsewhere).
132 lines
10 KiB
XML
132 lines
10 KiB
XML
<UserControl x:Class="ytLive.Controls.SettingsDrawer"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:models="clr-namespace:ytLive.Models"
|
|
xmlns:services="clr-namespace:ytLive.Services">
|
|
<!-- App Settings, as a RIGHT-EDGE PULL-OUT (creator ruling 2026-11-01): the gear tab opens
|
|
this drawer immediately, in the same animated-width pattern as Stream Settings / YPP /
|
|
Socials / TEST. It used to be a centred modal overlay, which then needed its own scroll
|
|
viewer once the section list outgrew the shell — a drawer has the height of the preview
|
|
and that problem disappears.
|
|
|
|
Categories are headings; their controls are indented under them (Zoom is one). -->
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
|
<StackPanel Margin="0,0,0,0">
|
|
|
|
<!-- ═══ RECORDINGS ═══ -->
|
|
<TextBlock Text="Recordings" Style="{StaticResource SectionHeader}" Margin="0,0,0,4"/>
|
|
<TextBlock Text="Default location" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="10,0,0,2"/>
|
|
<DockPanel Margin="10,0,0,10">
|
|
<Button DockPanel.Dock="Right" Content="Browse…" Command="{Binding ChooseRecordFolderCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" Padding="8,2" FontSize="11" Margin="6,0,0,0"/>
|
|
<Button DockPanel.Dock="Right" Content="Use Downloads" Command="{Binding ResetRecordFolderCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" Padding="8,2" FontSize="11" Margin="6,0,0,0"/>
|
|
<TextBox Style="{StaticResource YtTextBoxCompact}" Text="{Binding RecordFolderDisplay, Mode=OneWay}"
|
|
IsReadOnly="True" Foreground="{StaticResource Brush.OnSurfaceVariant}" VerticalAlignment="Center"/>
|
|
</DockPanel>
|
|
|
|
<!-- ═══ BRAND ═══ -->
|
|
<TextBlock Text="Brand logo" Style="{StaticResource SectionHeader}" Margin="0,6,0,4"/>
|
|
<TextBlock Text="Image file (shown on every scene)" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="10,0,0,2"/>
|
|
<DockPanel Margin="10,0,0,10">
|
|
<Button DockPanel.Dock="Right" Content="Browse…" Command="{Binding BrowseBrandLogoCommand}"
|
|
Style="{StaticResource YtButtonSecondary}" Padding="8,2" FontSize="11" Margin="6,0,0,0"/>
|
|
<!-- A file NAME says nothing about the picture. The thumbnail shows what is set;
|
|
hovering enlarges it, a click collapses it again. -->
|
|
<Border x:Name="BrandLogoThumbFrame" DockPanel.Dock="Left" Width="28" Height="28"
|
|
Margin="0,0,6,0" CornerRadius="4" ClipToBounds="True"
|
|
Background="{StaticResource Brush.SurfaceContainerLowest}"
|
|
BorderBrush="{StaticResource Brush.Outline}" BorderThickness="1"
|
|
Cursor="Hand" ToolTip="Hover to enlarge — click to close"
|
|
Visibility="{Binding BrandLogoPreviewImage, Converter={StaticResource NotNullToVis}}">
|
|
<Image x:Name="BrandLogoThumbImage" Source="{Binding BrandLogoPreviewImage}"
|
|
Stretch="Uniform" MouseEnter="BrandLogoThumb_MouseEnter"
|
|
MouseLeave="BrandLogoThumb_MouseLeave"
|
|
MouseLeftButtonUp="BrandLogoThumb_Click"/>
|
|
</Border>
|
|
<TextBox Style="{StaticResource YtTextBoxCompact}" Text="{Binding BrandLogoFileDisplay, Mode=OneWay}"
|
|
IsReadOnly="True" Foreground="{StaticResource Brush.OnSurfaceVariant}" VerticalAlignment="Center"/>
|
|
</DockPanel>
|
|
<Popup x:Name="BrandLogoPreviewPopup" PlacementTarget="{Binding ElementName=BrandLogoThumbFrame}"
|
|
Placement="Left" HorizontalOffset="-6" StaysOpen="True" AllowsTransparency="True"
|
|
IsHitTestVisible="True" MouseLeave="BrandLogoPreviewPopup_MouseLeave">
|
|
<Border Padding="6" CornerRadius="6"
|
|
Background="{StaticResource Brush.SurfaceContainerHighest}"
|
|
BorderBrush="{StaticResource Brush.Outline}" BorderThickness="1">
|
|
<StackPanel>
|
|
<Image Source="{Binding BrandLogoPreviewImage}" MaxWidth="420" MaxHeight="320"
|
|
Stretch="Uniform" RenderOptions.BitmapScalingMode="HighQuality"/>
|
|
<TextBlock Text="{Binding BrandLogoFileDisplay}" FontSize="11" Margin="0,6,0,0"
|
|
Foreground="{StaticResource Brush.OnSurfaceVariant}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
</Popup>
|
|
|
|
<!-- ═══ ZOOM ═══ -->
|
|
<TextBlock Text="Clips" Style="{StaticResource SectionHeader}" Margin="0,10,0,4"/>
|
|
<CheckBox Content="Save replay clips" Style="{StaticResource PropertyPillCheck}" Margin="12,2,0,4"
|
|
IsChecked="{Binding ClipsEnabled, Mode=TwoWay}"
|
|
ToolTip="F10 saves the last few seconds of the show. Off by default; nothing runs while it is off."/>
|
|
<StackPanel Margin="12,0,0,4" IsEnabled="{Binding ClipsEnabled}">
|
|
<TextBlock Text="Clip length" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="0,0,0,2"/>
|
|
<ComboBox ItemsSource="{Binding ClipLengthOptions}" SelectedItem="{Binding ClipLengthText, Mode=TwoWay}"
|
|
Style="{StaticResource YtComboBox}" Height="28" Margin="0,0,0,6"/>
|
|
<TextBlock Text="Keep" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="0,0,0,2"/>
|
|
<ComboBox ItemsSource="{Binding ClipKeepOptions}" SelectedItem="{Binding ClipKeepText, Mode=TwoWay}"
|
|
Style="{StaticResource YtComboBox}" Height="28"/>
|
|
<TextBlock Text="A capture, not an editor: for trimming, captions or a library, use a video editor."
|
|
Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="10" TextWrapping="Wrap" Margin="0,6,0,0"/>
|
|
</StackPanel>
|
|
|
|
<TextBlock Text="Zoom" Style="{StaticResource SectionHeader}" Margin="0,6,0,4"/>
|
|
|
|
<TextBlock Text="Zoom view shape" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="10,0,0,2"/>
|
|
<ComboBox Style="{StaticResource YtComboBox}" Margin="10,0,0,8" SelectedValue="{Binding ZoomShape}" SelectedValuePath="Tag">
|
|
<ComboBoxItem Content="Circle" Tag="{x:Static models:ZoomShape.Circle}"/>
|
|
<ComboBoxItem Content="Phone (Vertical Rectangle)" Tag="{x:Static models:ZoomShape.VerticalRectangle}"/>
|
|
<ComboBoxItem Content="Tablet (Horizontal Rectangle)" Tag="{x:Static models:ZoomShape.HorizontalRectangle}"/>
|
|
</ComboBox>
|
|
|
|
<DockPanel Margin="10,0,0,10">
|
|
<ToggleButton DockPanel.Dock="Right" Style="{StaticResource PillToggle}"
|
|
IsChecked="{Binding ZoomFollowsBox, Mode=TwoWay}" VerticalAlignment="Center"
|
|
ToolTip="Off: the box magnifies the area you clicked. On: it magnifies whatever it hovers over."/>
|
|
<TextBlock Text="Zoom box follows" Foreground="{StaticResource Brush.OnSurface}" FontSize="11" VerticalAlignment="Center"/>
|
|
</DockPanel>
|
|
|
|
<!-- ═══ VIDEO CLIPS (TASK 64) ═══ -->
|
|
<TextBlock Text="Video clips" Style="{StaticResource SectionHeader}" Margin="0,6,0,4"/>
|
|
<DockPanel Margin="10,0,0,10">
|
|
<ToggleButton DockPanel.Dock="Right" Style="{StaticResource PillToggle}"
|
|
IsChecked="{Binding AutoChromaScreen, Mode=TwoWay}" VerticalAlignment="Center"
|
|
ToolTip="On: a clip shot against a clear green or blue screen is keyed as soon as it is added. Off: the app asks first."/>
|
|
<StackPanel>
|
|
<TextBlock Text="Auto Green/Blue Screen" Foreground="{StaticResource Brush.OnSurface}" FontSize="11"/>
|
|
<TextBlock Text="Removes a detected screen without asking." Style="{StaticResource PropertyHint}"/>
|
|
</StackPanel>
|
|
</DockPanel>
|
|
|
|
<!-- ═══ SCENE TRANSITIONS ═══ -->
|
|
<TextBlock Text="Scene transition" Style="{StaticResource SectionHeader}" Margin="0,6,0,4"/>
|
|
<TextBlock Text="Type" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" Margin="10,0,0,2"/>
|
|
<ComboBox Style="{StaticResource YtComboBox}" Margin="10,0,0,8" SelectedValue="{Binding SelectedTransitionType}" SelectedValuePath="Tag">
|
|
<ComboBoxItem Content="Cut" Tag="{x:Static services:TransitionType.Cut}"/>
|
|
<ComboBoxItem Content="Fade" Tag="{x:Static services:TransitionType.Fade}"/>
|
|
<ComboBoxItem Content="Move" Tag="{x:Static services:TransitionType.Move}"/>
|
|
<ComboBoxItem Content="Wipe" Tag="{x:Static services:TransitionType.Wipe}"/>
|
|
</ComboBox>
|
|
<DockPanel Margin="10,0,0,10">
|
|
<TextBlock DockPanel.Dock="Right" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" VerticalAlignment="Center" Margin="8,0,0,0" Width="56">
|
|
<Run Text="{Binding TransitionDurationMs, StringFormat={}{0:0}}"/><Run Text=" ms"/>
|
|
</TextBlock>
|
|
<Slider Minimum="100" Maximum="2000" TickFrequency="50" IsSnapToTickEnabled="True"
|
|
Value="{Binding TransitionDurationMs, Mode=TwoWay}" VerticalAlignment="Center"/>
|
|
</DockPanel>
|
|
|
|
<!-- Development panel host. Empty in a Release build: the panel itself is excluded
|
|
from the Release compile, and the code-behind only fills this inside #if DEBUG. -->
|
|
<StackPanel x:Name="DeveloperPanelHost"/>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</UserControl>
|