OF-DL/OF DL.Gui/Views/MainWindow.axaml

1630 lines
119 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<Window xmlns="https://github.com/avaloniaui"
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:controls="using:OF_DL.Gui.Controls"
xmlns:vm="using:OF_DL.Gui.ViewModels"
xmlns:views="using:OF_DL.Gui.Views"
x:Class="OF_DL.Gui.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Width="1320"
Height="860"
MinWidth="1150"
MinHeight="700"
Title="OF DL"
Background="{DynamicResource WindowBackgroundBrush}"
mc:Ignorable="d">
<Window.Styles>
<Style Selector="Border.surface">
<Setter Property="Background" Value="{DynamicResource SurfaceBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="12" />
<Setter Property="BoxShadow" Value="0 1 3 0 #0F000000, 0 1 2 -1 #0F000000" />
</Style>
<Style Selector="Button.primary">
<Setter Property="Background" Value="{DynamicResource PrimaryButtonBackgroundBrush}" />
<Setter Property="Foreground" Value="{DynamicResource PrimaryButtonForegroundBrush}" />
<Setter Property="Padding" Value="16,8" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Transitions">
<Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.15" />
<BrushTransition Property="Background" Duration="0:0:0.15" />
</Transitions>
</Setter>
</Style>
<Style Selector="Button.primary:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource PrimaryButtonBackgroundHoverBrush}" />
</Style>
<Style Selector="Button.primary:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource PrimaryButtonBackgroundPressedBrush}" />
<Setter Property="RenderTransform" Value="scale(0.98)" />
</Style>
<Style Selector="Button.secondary">
<Setter Property="Background" Value="{DynamicResource SecondaryButtonBackgroundBrush}" />
<Setter Property="Foreground" Value="{DynamicResource SecondaryButtonForegroundBrush}" />
<Setter Property="Padding" Value="16,7" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderBrush" Value="{DynamicResource SecondaryButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Transitions">
<Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.15" />
<BrushTransition Property="Background" Duration="0:0:0.15" />
</Transitions>
</Setter>
</Style>
<Style Selector="Button.secondary:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource SecondaryButtonBackgroundHoverBrush}" />
</Style>
<Style Selector="Button.secondary:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource SecondaryButtonBackgroundPressedBrush}" />
<Setter Property="RenderTransform" Value="scale(0.98)" />
</Style>
<Style Selector="Button.link">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Foreground" Value="{DynamicResource PrimaryButtonBackgroundBrush}" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style Selector="Button.link:pointerover">
<Setter Property="Foreground" Value="{DynamicResource PrimaryButtonBackgroundHoverBrush}" />
</Style>
<Style Selector="TextBox.fileNameOverlayInput:not(:empty)">
<Setter Property="Foreground" Value="Transparent" />
</Style>
<!-- Modern TextBox Styling -->
<Style Selector="TextBox">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="10,7" />
<Setter Property="Transitions">
<Transitions>
<BrushTransition Property="BorderBrush" Duration="0:0:0.15" />
</Transitions>
</Setter>
</Style>
<Style Selector="TextBox:focus">
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryButtonBackgroundBrush}" />
</Style>
<!-- Modern ComboBox Styling -->
<Style Selector="ComboBox">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="10,8" />
</Style>
<!-- Modern AutoCompleteBox Styling -->
<Style Selector="AutoCompleteBox">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="10,8" />
</Style>
<!-- Modern DatePicker Styling -->
<Style Selector="DatePicker">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<Style Selector="DatePicker /template/ Button">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="10,8" />
<Setter Property="MinHeight" Value="36" />
</Style>
<Style Selector="DatePicker /template/ TextBlock">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0" />
</Style>
<!-- Modern NumericUpDown Styling -->
<Style Selector="NumericUpDown">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<!-- Modern CheckBox Styling -->
<Style Selector="CheckBox">
<Setter Property="Padding" Value="8,6" />
</Style>
<!-- Modern ProgressBar Styling -->
<Style Selector="ProgressBar">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Height" Value="8" />
</Style>
<!-- Modern ListBox Styling -->
<Style Selector="ListBox">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<Style Selector="Border.copyToast">
<Setter Property="Background" Value="{DynamicResource PrimaryButtonBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="10" />
<Setter Property="Padding" Value="12,8" />
<Setter Property="Opacity" Value="0" />
<Setter Property="BoxShadow" Value="0 6 12 -4 #33000000, 0 2 4 -2 #26000000" />
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Opacity" Duration="0:0:0.18" />
</Transitions>
</Setter>
</Style>
</Window.Styles>
<Grid RowDefinitions="Auto,Auto,*">
<Menu Grid.Row="0">
<MenuItem Header="_File">
<MenuItem Header="_Refresh" Command="{Binding RefreshUsersCommand}" />
<MenuItem Header="_Logout"
IsVisible="{Binding IsAuthenticated}"
Command="{Binding LogoutCommand}" />
<Separator />
<MenuItem Header="E_xit" Command="{Binding ExitApplicationCommand}" />
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem Header="_Configuration" Command="{Binding EditConfigCommand}" />
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_Join Discord" Click="OnJoinDiscordClick" />
<Separator />
<MenuItem Header="FA_Q" Click="OnFaqClick" />
<MenuItem Header="_Documentation" Click="OnDocumentationClick" />
<Separator />
<MenuItem Header="_About" Click="OnAboutClick" />
</MenuItem>
</Menu>
<Border Grid.Row="1"
Padding="18,14"
BorderThickness="0,0,0,1"
BorderBrush="{DynamicResource TopBarBorderBrush}"
Background="{DynamicResource TopBarBackgroundBrush}">
<Grid ColumnDefinitions="*,Auto" VerticalAlignment="Center">
<TextBlock Grid.Column="0"
Foreground="{DynamicResource TopBarTextBrush}"
FontWeight="SemiBold"
Text="{Binding AuthenticatedUserDisplay}"
TextWrapping="Wrap"
VerticalAlignment="Center" />
<StackPanel Grid.Column="1"
Orientation="Horizontal"
Spacing="8"
HorizontalAlignment="Right">
<Button Classes="secondary"
IsVisible="{Binding IsAuthenticated}"
Command="{Binding LogoutCommand}"
Content="Logout" />
</StackPanel>
</Grid>
</Border>
<Grid Grid.Row="2" Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<StackPanel IsVisible="{Binding IsLoadingScreen}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="12"
Width="420">
<TextBlock HorizontalAlignment="Center"
FontSize="22"
FontWeight="SemiBold"
Text="Loading" />
<ProgressBar IsIndeterminate="True" Height="14" />
<TextBlock HorizontalAlignment="Center" Text="{Binding LoadingMessage}" TextWrapping="Wrap" />
</StackPanel>
<ScrollViewer IsVisible="{Binding IsConfigScreen}"
VerticalScrollBarVisibility="Auto">
<StackPanel Spacing="20" Margin="2,0,4,0">
<TextBlock FontSize="24" FontWeight="SemiBold" Text="Configuration"
Foreground="{DynamicResource TextPrimaryBrush}" />
<Border Classes="surface" Padding="20" Margin="0,0,0,2">
<StackPanel Spacing="8">
<TextBlock FontSize="16"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Download Media Types and Sources" />
<StackPanel Spacing="4">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}" Text="Media Types" />
<ItemsControl ItemsSource="{Binding MediaTypeOptions}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:MultiSelectOptionViewModel">
<StackPanel Margin="0,0,14,6" Orientation="Horizontal" Spacing="6">
<CheckBox Content="{Binding DisplayName}"
IsChecked="{Binding IsSelected}" />
<Button IsVisible="{Binding HasHelpText}"
Width="18"
Height="18"
MinWidth="18"
MinHeight="18"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="11"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="9"
Content="?"
ToolTip.Tip="{Binding HelpText}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock IsVisible="{Binding HasMediaTypesError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding MediaTypesError}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel Spacing="4">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}" Text="Sources" />
<ItemsControl ItemsSource="{Binding MediaSourceOptions}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:MultiSelectOptionViewModel">
<StackPanel Margin="0,0,14,6" Orientation="Horizontal" Spacing="6">
<CheckBox Content="{Binding DisplayName}"
IsChecked="{Binding IsSelected}" />
<Button IsVisible="{Binding HasHelpText}"
Width="18"
Height="18"
MinWidth="18"
MinHeight="18"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="11"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="9"
Content="?"
ToolTip.Tip="{Binding HelpText}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock IsVisible="{Binding HasMediaSourcesError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding MediaSourcesError}"
TextWrapping="Wrap" />
</StackPanel>
</StackPanel>
</Border>
<Grid ColumnDefinitions="*,*" Margin="0,0,0,2">
<ItemsControl x:Name="LeftConfigCategories"
Grid.Column="0"
Margin="0,0,6,0"
ItemsSource="{Binding ConfigCategoriesLeft}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:ConfigCategoryViewModel">
<Border Classes="surface"
Margin="0,0,0,16"
HorizontalAlignment="Stretch"
Padding="20">
<StackPanel Spacing="8">
<TextBlock FontSize="16"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="{Binding CategoryName}" />
<StackPanel IsVisible="{Binding IsExternal}"
Spacing="10"
Margin="0,0,0,0">
<StackPanel Orientation="Horizontal" Spacing="6">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="FFmpeg Path" />
<Button Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding ViewModel.FfmpegPathHelpText, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}" />
</StackPanel>
<Grid ColumnDefinitions="*,Auto">
<TextBox Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Text="{Binding ViewModel.FfmpegPath, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
Watermark="Optional: path to FFmpeg executable" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Browse..."
Click="OnBrowseFfmpegPathClick" />
</Grid>
<TextBlock
IsVisible="{Binding ViewModel.HasFfmpegPathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=False}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding ViewModel.FfmpegPathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
TextWrapping="Wrap" />
<StackPanel Orientation="Horizontal" Spacing="6">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="FFprobe Path" />
<Button Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding ViewModel.FfprobePathHelpText, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}" />
</StackPanel>
<Grid ColumnDefinitions="*,Auto">
<TextBox Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Text="{Binding ViewModel.FfprobePath, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
Watermark="Optional: path to FFprobe executable" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Browse..."
Click="OnBrowseFfprobePathClick" />
</Grid>
<TextBlock
IsVisible="{Binding ViewModel.HasFfprobePathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=False}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding ViewModel.FfprobePathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel IsVisible="{Binding IsDownloadBehavior}"
Spacing="10"
Margin="0,0,0,0">
<StackPanel Orientation="Horizontal" Spacing="6">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Download Path" />
<Button Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding ViewModel.DownloadPathHelpText, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}" />
</StackPanel>
<Grid ColumnDefinitions="*,Auto">
<TextBox Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Text="{Binding ViewModel.DownloadPath, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
Watermark="Select download folder" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Browse..."
Click="OnBrowseDownloadPathClick" />
</Grid>
<TextBlock
IsVisible="{Binding ViewModel.HasDownloadPathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=False}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding ViewModel.DownloadPathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
TextWrapping="Wrap" />
<StackPanel IsVisible="{Binding HasSpecificDateFilterFields}"
Margin="0"
Spacing="6"
HorizontalAlignment="Stretch"
x:CompileBindings="False">
<StackPanel Orientation="Horizontal"
Spacing="6"
VerticalAlignment="Center">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Download Posts from Specific Dates"
VerticalAlignment="Center"
TextWrapping="Wrap" />
<Button
IsVisible="{Binding HasSpecificDateFilterHelpText}"
Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding SpecificDateFilterHelpText}" />
</StackPanel>
<Grid ColumnDefinitions="Auto,Auto,Auto"
HorizontalAlignment="Left">
<CheckBox Grid.Column="0"
Content="Enable"
VerticalAlignment="Center"
Margin="0,0,8,0"
IsChecked="{Binding DownloadOnlySpecificDatesField.BoolValue, FallbackValue=False}" />
<ComboBox Grid.Column="1"
Width="140"
VerticalAlignment="Center"
Margin="0,0,8,0"
IsEnabled="{Binding DownloadOnlySpecificDatesField.BoolValue, FallbackValue=False}"
ItemsSource="{Binding DownloadDateSelectionField.EnumOptions, FallbackValue={x:Null}}"
SelectedItem="{Binding DownloadDateSelectionField.EnumValue, FallbackValue={x:Null}}" />
<DatePicker Grid.Column="2"
MinWidth="200"
VerticalAlignment="Center"
IsEnabled="{Binding DownloadOnlySpecificDatesField.BoolValue, FallbackValue=False}"
SelectedDate="{Binding CustomDateField.DateValue, FallbackValue={x:Null}}" />
</Grid>
</StackPanel>
<Grid IsVisible="{Binding HasDownloadVideoResolutionField}"
Margin="0"
ColumnDefinitions="190,*"
x:CompileBindings="False">
<Grid Grid.Column="0"
ColumnDefinitions="*,Auto"
Margin="0,6,10,0"
ClipToBounds="True">
<TextBlock Grid.Column="0"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="{Binding DownloadVideoResolutionField.DisplayName}"
TextWrapping="Wrap"
VerticalAlignment="Top" />
<Button Grid.Column="1"
IsVisible="{Binding DownloadVideoResolutionField.HasHelpText}"
Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Margin="6,0,0,0"
Padding="0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding DownloadVideoResolutionField.HelpText}" />
</Grid>
<StackPanel Grid.Column="1" Spacing="4">
<ComboBox HorizontalAlignment="Left"
MinWidth="160"
ItemsSource="{Binding DownloadVideoResolutionField.EnumOptions, FallbackValue={x:Null}}"
SelectedItem="{Binding DownloadVideoResolutionField.EnumValue, FallbackValue={x:Null}}" />
<TextBlock
IsVisible="{Binding DownloadVideoResolutionField.HasError, FallbackValue=False}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding DownloadVideoResolutionField.ErrorMessage, FallbackValue=''}"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
<Grid Margin="0" ColumnDefinitions="190,*">
<Grid Grid.Column="0"
ColumnDefinitions="*,Auto"
Margin="0,6,10,0"
ClipToBounds="True">
<TextBlock Grid.Column="0"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="DRM Video Duration Match Threshold"
TextWrapping="Wrap"
VerticalAlignment="Top" />
<Button Grid.Column="1"
Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Margin="6,0,0,0"
Padding="0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding ViewModel.DrmVideoDurationMatchThresholdHelpText, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}" />
</Grid>
<Grid Grid.Column="1" ColumnDefinitions="*,Auto"
VerticalAlignment="Center">
<Slider Grid.Column="0"
Minimum="0"
Maximum="100"
Value="{Binding ViewModel.DrmVideoDurationMatchThresholdPercent, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=98}" />
<TextBlock Grid.Column="1"
Margin="10,0,0,0"
VerticalAlignment="Center"
FontWeight="SemiBold"
Foreground="{DynamicResource TextSecondaryBrush}"
Text="{Binding ViewModel.DrmVideoDurationMatchThresholdPercentLabel, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue='98%'}" />
</Grid>
</Grid>
</StackPanel>
<Grid IsVisible="{Binding HasRateLimitFields}"
Margin="0,0,0,10"
ColumnDefinitions="190,*"
x:CompileBindings="False">
<Grid Grid.Column="0"
ColumnDefinitions="*,Auto"
Margin="0,6,10,0"
ClipToBounds="True">
<TextBlock Grid.Column="0"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Limit Download Rate"
TextWrapping="Wrap"
VerticalAlignment="Top" />
<Button Grid.Column="1"
IsVisible="{Binding HasRateLimitHelpText}"
Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Margin="6,0,0,0"
Padding="0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding RateLimitHelpText}" />
</Grid>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
Spacing="8"
VerticalAlignment="Center">
<CheckBox Content="Enable"
IsChecked="{Binding LimitDownloadRateField.BoolValue, FallbackValue=False}" />
<NumericUpDown MinWidth="120"
IsEnabled="{Binding LimitDownloadRateField.BoolValue, FallbackValue=False}"
Value="{Binding DownloadLimitInMbPerSecField.NumericValue, FallbackValue=0}"
Increment="1"
FormatString="N0" />
<TextBlock Text="Mbps"
Foreground="{DynamicResource TextSecondaryBrush}"
VerticalAlignment="Center" />
</StackPanel>
</Grid>
<Grid IsVisible="{Binding HasFolderStructureFields}"
Margin="0,0,0,10"
ColumnDefinitions="190,*"
x:CompileBindings="False">
<Grid Grid.Column="0"
ColumnDefinitions="*,Auto"
Margin="0,6,10,0"
ClipToBounds="True">
<TextBlock Grid.Column="0"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Create Separate Folders For Each"
TextWrapping="Wrap"
VerticalAlignment="Top" />
<Button Grid.Column="1"
IsVisible="{Binding HasFolderStructureHelpText}"
Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Margin="6,0,0,0"
Padding="0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding FolderStructureHelpText}" />
</Grid>
<StackPanel Grid.Column="1" Spacing="6">
<CheckBox Content="Free Posts"
IsChecked="{Binding FolderPerPostField.BoolValue, FallbackValue=False}" />
<CheckBox Content="Paid Posts"
IsChecked="{Binding FolderPerPaidPostField.BoolValue, FallbackValue=False}" />
<CheckBox Content="Free Messages"
IsChecked="{Binding FolderPerMessageField.BoolValue, FallbackValue=False}" />
<CheckBox Content="Paid Messages"
IsChecked="{Binding FolderPerPaidMessageField.BoolValue, FallbackValue=False}" />
</StackPanel>
</Grid>
<ItemsControl ItemsSource="{Binding Fields}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="10" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:ConfigFieldViewModel">
<Grid Margin="0" ColumnDefinitions="190,*">
<Grid Grid.Column="0"
ColumnDefinitions="*,Auto"
Margin="0,6,10,0"
ClipToBounds="True">
<TextBlock Grid.Column="0"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="{Binding DisplayName}"
TextWrapping="Wrap"
VerticalAlignment="Top" />
<Button Grid.Column="1"
IsVisible="{Binding HasHelpText}"
Width="20"
Height="20"
MinWidth="20"
MinHeight="20"
Margin="6,0,0,0"
Padding="0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="12"
FontWeight="Bold"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Content="?"
ToolTip.Tip="{Binding HelpText}" />
</Grid>
<StackPanel Grid.Column="1" Spacing="4">
<StackPanel IsVisible="{Binding IsBoolean}"
Orientation="Horizontal"
Spacing="8">
<CheckBox IsChecked="{Binding BoolValue}"
VerticalAlignment="Center" />
<TextBlock
IsVisible="{Binding IsHideMissingCdmKeysWarningField}"
VerticalAlignment="Center"
Text="{Binding ViewModel.HideMissingCdmKeysWarningStatusText, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
Foreground="{Binding ViewModel.HideMissingCdmKeysWarningStatusBrush, RelativeSource={RelativeSource AncestorType=views:MainWindow}}" />
</StackPanel>
<ComboBox IsVisible="{Binding IsEnum}"
HorizontalAlignment="Left"
MinWidth="160"
ItemsSource="{Binding EnumOptions}"
SelectedItem="{Binding EnumValue}" />
<DatePicker IsVisible="{Binding IsDate}"
HorizontalAlignment="Stretch"
SelectedDate="{Binding DateValue}" />
<NumericUpDown
IsVisible="{Binding IsNumericAndNotTimeout}"
HorizontalAlignment="Left"
MinWidth="120"
Value="{Binding NumericValue}"
Increment="1"
FormatString="N0" />
<StackPanel
IsVisible="{Binding IsTimeoutField}"
Orientation="Horizontal"
Spacing="8">
<NumericUpDown MinWidth="120"
Minimum="-1"
Value="{Binding NumericValue}"
Increment="1"
FormatString="N0" />
<TextBlock Text="seconds"
Foreground="{DynamicResource TextSecondaryBrush}"
VerticalAlignment="Center" />
</StackPanel>
<TextBox
IsVisible="{Binding IsRegularTextInput}"
HorizontalAlignment="Stretch"
AcceptsReturn="{Binding IsMultiline}"
TextWrapping="Wrap"
MinHeight="{Binding TextBoxMinHeight}"
Text="{Binding TextValue}" />
<Grid x:Name="IgnoredUsersListGrid"
IsVisible="{Binding IsIgnoredUsersListField}"
ColumnDefinitions="*,Auto"
x:CompileBindings="False">
<ComboBox Grid.Column="0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding IgnoredUsersListOptions}"
SelectedItem="{Binding SelectedIgnoredUsersListOption}">
<ComboBox.ItemTemplate>
<DataTemplate
x:DataType="vm:ConfigSelectOptionViewModel">
<TextBlock
Text="{Binding DisplayName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Grid.Column="1"
Width="34"
Height="34"
MinWidth="34"
MinHeight="34"
Margin="8,0,0,0"
Padding="0"
FontSize="16"
FontWeight="SemiBold"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="8"
Content="⟳"
ToolTip.Tip="Refresh list names from OnlyFans"
Command="{Binding ViewModel.RefreshIgnoredUsersListsCommand, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue={x:Null}}"
CommandParameter="{Binding}" />
</Grid>
<StackPanel
IsVisible="{Binding IsFileNameFormatField}"
Spacing="6">
<Grid ClipToBounds="True">
<TextBox
x:Name="ConfigFileNameFormatTextBox"
Classes="fileNameOverlayInput"
HorizontalAlignment="Stretch"
Text="{Binding TextValue}"
Padding="8,6"
CaretBrush="{DynamicResource TextPrimaryBrush}" />
<controls:FileNameFormatOverlayTextBlock
IsHitTestVisible="False"
Margin="{Binding #ConfigFileNameFormatTextBox.Padding}"
VerticalAlignment="Center"
Segments="{Binding FileNameFormatSegments}"
SourceTextBox="{Binding #ConfigFileNameFormatTextBox}"
FontFamily="{Binding #ConfigFileNameFormatTextBox.FontFamily}"
FontSize="{Binding #ConfigFileNameFormatTextBox.FontSize}"
FontWeight="{Binding #ConfigFileNameFormatTextBox.FontWeight}"
FontStyle="{Binding #ConfigFileNameFormatTextBox.FontStyle}" />
</Grid>
<Grid ColumnDefinitions="*,Auto">
<ComboBox Grid.Column="0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding AvailableFileNameVariables}"
SelectedItem="{Binding SelectedFileNameVariable}" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Insert Variable"
Command="{Binding InsertSelectedFileNameVariableCommand}" />
</Grid>
<TextBlock
IsVisible="{Binding HasUnknownFileNameVariables}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding UnknownFileNameVariablesMessage}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel
IsVisible="{Binding IsCreatorConfigsField}"
Spacing="6">
<Button Classes="secondary"
HorizontalAlignment="Left"
Command="{Binding ViewModel.AddCreatorConfigCommand, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue={x:Null}}">
<StackPanel
Orientation="Horizontal"
Spacing="6">
<TextBlock Text="+"
FontWeight="Bold" />
<TextBlock Text="Add Creator" />
</StackPanel>
</Button>
<ScrollViewer MaxHeight="264">
<ItemsControl
ItemsSource="{Binding ViewModel.CreatorConfigEditor.Rows, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue={x:Null}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="6" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate
x:DataType="vm:CreatorConfigRowViewModel">
<Border
Background="{DynamicResource PreviewBackgroundBrush}"
BorderBrush="{DynamicResource PreviewBorderBrush}"
BorderThickness="1"
CornerRadius="8"
Padding="10">
<Grid
ColumnDefinitions="*,Auto,Auto">
<TextBlock
Grid.Column="0"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="{Binding Username}"
VerticalAlignment="Center" />
<Button
Grid.Column="1"
Width="28"
Height="28"
MinWidth="28"
MinHeight="28"
Margin="0,0,6,0"
Padding="0"
FontSize="14"
FontWeight="SemiBold"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{DynamicResource HelpBadgeBackgroundBrush}"
BorderBrush="{DynamicResource HelpBadgeBorderBrush}"
BorderThickness="1"
CornerRadius="6"
Content="✎"
ToolTip.Tip="Edit"
Command="{Binding EditCommand}" />
<Button
Grid.Column="2"
Width="28"
Height="28"
MinWidth="28"
MinHeight="28"
Padding="0"
FontSize="14"
FontWeight="SemiBold"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{DynamicResource DangerSoftBackgroundBrush}"
BorderBrush="{DynamicResource DangerSoftBorderBrush}"
BorderThickness="1"
CornerRadius="6"
Content="×"
ToolTip.Tip="Delete"
Command="{Binding DeleteCommand}" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
<TextBlock IsVisible="{Binding HasError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding ErrorMessage}"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Column="1"
Margin="6,0,0,0"
ItemsSource="{Binding ConfigCategoriesRight}"
ItemTemplate="{Binding ItemTemplate, ElementName=LeftConfigCategories}" />
</Grid>
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
<Button Content="Save Configuration"
Classes="primary"
Command="{Binding SaveConfigCommand}" />
<Button Content="Cancel"
Classes="secondary"
Command="{Binding CancelConfigCommand}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
<StackPanel IsVisible="{Binding IsAuthScreen}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="640"
Spacing="14">
<TextBlock HorizontalAlignment="Center"
FontSize="24"
FontWeight="SemiBold"
Text="Authentication Required" />
<TextBlock TextWrapping="Wrap"
TextAlignment="Center"
HorizontalAlignment="Center"
Text="{Binding AuthScreenMessage}" />
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center">
<Button Content="Login with Browser"
Classes="primary"
IsEnabled="{Binding !IsBrowserLoginInProgress}"
Command="{Binding StartBrowserLoginCommand}" />
<Button Content="Manual Authentication"
Classes="secondary"
IsEnabled="{Binding !IsBrowserLoginInProgress}"
Command="{Binding OpenManualAuthScreenCommand}" />
</StackPanel>
</StackPanel>
<StackPanel IsVisible="{Binding IsManualAuthScreen}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="760"
Spacing="14">
<TextBlock HorizontalAlignment="Center"
FontSize="24"
FontWeight="SemiBold"
Text="Manual Authentication" />
<StackPanel HorizontalAlignment="Center" Spacing="8">
<TextBlock TextWrapping="Wrap"
TextAlignment="Center"
HorizontalAlignment="Center"
Foreground="{DynamicResource TextSecondaryBrush}"
Text="{Binding ManualAuthInstructionsText}" />
<Button Classes="link"
HorizontalAlignment="Center"
Content="https://docs.ofdl.tools/config/auth/#legacy-methods"
Click="OnAuthLegacyMethodsClick" />
</StackPanel>
<TextBlock TextWrapping="Wrap"
TextAlignment="Center"
HorizontalAlignment="Center"
Text="{Binding ManualAuthScreenMessage}" />
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center">
<Button Content="Go Back"
Classes="secondary"
Command="{Binding GoBackToAuthScreenCommand}" />
<Button Content="Continue"
Classes="primary"
Command="{Binding ContinueWithManualAuthCommand}" />
</StackPanel>
</StackPanel>
<Grid IsVisible="{Binding IsUserSelectionScreen}" RowDefinitions="Auto,*,Auto"
ColumnDefinitions="2*,3*">
<Border Grid.Row="0"
Grid.ColumnSpan="2"
Padding="16"
Margin="0,0,0,16"
Classes="surface">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0"
Orientation="Horizontal"
Spacing="8"
VerticalAlignment="Center">
<Button Content="Download Selected"
Classes="primary"
Command="{Binding DownloadSelectedCommand}" />
<Button Content="Download Purchased Tab"
Classes="secondary"
Command="{Binding DownloadPurchasedTabCommand}" />
<Button Content="Download Single Post/Message"
Classes="secondary"
Command="{Binding OpenSinglePostOrMessageModalCommand}" />
</StackPanel>
<Button Grid.Column="1"
IsVisible="{Binding IsDownloading}"
Classes="primary"
Background="{DynamicResource DangerButtonBackgroundBrush}"
Command="{Binding StopWorkCommand}"
Content="Stop" />
</Grid>
</Border>
<Border Grid.Row="1"
Grid.Column="0"
Margin="0,0,8,0"
Padding="16"
Classes="surface">
<Grid RowDefinitions="Auto,*">
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" VerticalAlignment="Center">
<StackPanel Grid.Column="0" Spacing="3">
<TextBlock FontWeight="SemiBold" Foreground="{DynamicResource TextPrimaryBrush}"
Text="Users" />
<CheckBox IsThreeState="True"
IsChecked="{Binding AllUsersSelected}"
Content="{Binding SelectedUsersSummary}"
IsEnabled="{Binding !IsDownloading}" />
</StackPanel>
<ComboBox Grid.Column="1"
Width="280"
VerticalAlignment="Center"
PlaceholderText="Select a list of users"
ItemsSource="{Binding UserLists}"
SelectedItem="{Binding SelectedListName}"
IsEnabled="{Binding !IsDownloading}" />
</Grid>
<ListBox Grid.Row="1" Margin="0,8,0,0" ItemsSource="{Binding AvailableUsers}"
Background="{DynamicResource SurfaceBackgroundBrush}"
BorderBrush="Transparent"
BorderThickness="0"
IsEnabled="{Binding !IsDownloading}">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="0" />
</Style>
<Style Selector="ListBoxItem:selected /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="ListBoxItem:selected:focus /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="ListBoxItem:selected:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent" />
</Style>
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:SelectableUserViewModel">
<CheckBox IsChecked="{Binding IsSelected}"
HorizontalAlignment="Stretch">
<TextBlock Text="{Binding Username}" />
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>
<Border Grid.Row="1"
Grid.Column="1"
Margin="8,0,0,0"
Padding="16"
Classes="surface">
<Grid RowDefinitions="Auto,*">
<TextBlock Grid.Row="0" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}" Text="Activity Log" />
<ListBox Grid.Row="1"
x:Name="ActivityLogListBox"
Margin="0,8,0,0"
ItemsSource="{Binding ActivityLog}"
Background="{DynamicResource SurfaceBackgroundBrush}"
BorderBrush="Transparent"
BorderThickness="0"
SelectionMode="Single">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.Styles>
</ListBox>
</Grid>
</Border>
<Border Grid.Row="2"
Grid.ColumnSpan="2" Grid.Column="0"
Margin="0,16,0,0"
Padding="16"
Classes="surface"
IsVisible="{Binding IsDownloadProgressVisible}">
<StackPanel Spacing="8">
<TextBlock FontWeight="SemiBold" Foreground="{DynamicResource TextPrimaryBrush}"
Text="{Binding DownloadProgressDescription}" />
<ProgressBar IsIndeterminate="{Binding IsDownloadProgressIndeterminate}"
Minimum="0"
Maximum="{Binding DownloadProgressMaximum}"
Value="{Binding DownloadProgressValue}" />
</StackPanel>
</Border>
</Grid>
<StackPanel IsVisible="{Binding IsErrorScreen}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="640"
Spacing="14">
<TextBlock HorizontalAlignment="Center"
FontSize="24"
FontWeight="SemiBold"
Text="Startup Error" />
<TextBlock TextWrapping="Wrap" Text="{Binding ErrorMessage}" />
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center">
<Button Content="Retry Startup" Classes="primary" Command="{Binding RetryStartupCommand}" />
</StackPanel>
</StackPanel>
</Grid>
</Grid>
<!-- Modal Overlay -->
<Grid Grid.Row="0" Grid.RowSpan="3"
IsVisible="{Binding CreatorConfigEditor.ModalViewModel.IsOpen}"
Background="{DynamicResource OverlayBackgroundBrush}"
ZIndex="1000"
PointerPressed="OnModalOverlayClicked">
<Border Background="{DynamicResource ModalBackgroundBrush}"
BorderBrush="{DynamicResource ModalBorderBrush}"
BorderThickness="1"
CornerRadius="16"
Padding="32"
Width="700"
MaxHeight="750"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BoxShadow="0 20 25 -5 #19000000, 0 10 10 -5 #0F000000"
PointerPressed="OnModalContentClicked">
<ScrollViewer DataContext="{Binding CreatorConfigEditor.ModalViewModel}">
<StackPanel Spacing="14" Margin="8,4,8,4" x:DataType="vm:CreatorConfigModalViewModel">
<TextBlock FontSize="18"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="{Binding DialogTitle}" />
<StackPanel Spacing="6">
<TextBlock FontWeight="SemiBold" Foreground="{DynamicResource TextPrimaryBrush}"
Text="Username" />
<Grid ColumnDefinitions="*,Auto">
<AutoCompleteBox Grid.Column="0"
Text="{Binding Username}"
ItemsSource="{Binding AvailableUsers}"
Watermark="Enter or select username"
FilterMode="Contains" />
</Grid>
<TextBlock IsVisible="{Binding HasUsernameError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding UsernameError}"
TextWrapping="Wrap" />
</StackPanel>
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextSecondaryBrush}"
Text="File Name Formats (leave blank to use global defaults)" />
<StackPanel Spacing="8">
<TextBlock FontWeight="SemiBold" Foreground="{DynamicResource TextPrimaryBrush}"
Text="Free Post File Name Format" />
<Grid ClipToBounds="True">
<TextBox x:Name="PostFileNameFormatTextBox"
Classes="fileNameOverlayInput"
Text="{Binding PostFileNameFormat}"
Watermark="Optional: override global free post format"
Padding="8,6"
CaretBrush="{DynamicResource TextPrimaryBrush}" />
<controls:FileNameFormatOverlayTextBlock IsHitTestVisible="False"
Margin="{Binding #PostFileNameFormatTextBox.Padding}"
VerticalAlignment="Center"
Segments="{Binding PostSegments}"
SourceTextBox="{Binding #PostFileNameFormatTextBox}"
FontFamily="{Binding #PostFileNameFormatTextBox.FontFamily}"
FontSize="{Binding #PostFileNameFormatTextBox.FontSize}"
FontWeight="{Binding #PostFileNameFormatTextBox.FontWeight}"
FontStyle="{Binding #PostFileNameFormatTextBox.FontStyle}" />
</Grid>
<Grid ColumnDefinitions="*,Auto">
<ComboBox Grid.Column="0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding PostVariables}"
SelectedItem="{Binding SelectedPostVariable}" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Insert Variable"
Command="{Binding InsertPostVariableCommand}" />
</Grid>
<TextBlock IsVisible="{Binding HasUnknownPostVariables}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding UnknownPostVariablesMessage}"
TextWrapping="Wrap" />
<TextBlock IsVisible="{Binding HasPostFileNameFormatError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding PostFileNameFormatError}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel Spacing="8">
<TextBlock FontWeight="SemiBold" Foreground="{DynamicResource TextPrimaryBrush}"
Text="Paid Post File Name Format" />
<Grid ClipToBounds="True">
<TextBox x:Name="PaidPostFileNameFormatTextBox"
Classes="fileNameOverlayInput"
Text="{Binding PaidPostFileNameFormat}"
Watermark="Optional: override global paid post format"
Padding="8,6"
CaretBrush="{DynamicResource TextPrimaryBrush}" />
<controls:FileNameFormatOverlayTextBlock IsHitTestVisible="False"
Margin="{Binding #PaidPostFileNameFormatTextBox.Padding}"
VerticalAlignment="Center"
Segments="{Binding PaidPostSegments}"
SourceTextBox="{Binding #PaidPostFileNameFormatTextBox}"
FontFamily="{Binding #PaidPostFileNameFormatTextBox.FontFamily}"
FontSize="{Binding #PaidPostFileNameFormatTextBox.FontSize}"
FontWeight="{Binding #PaidPostFileNameFormatTextBox.FontWeight}"
FontStyle="{Binding #PaidPostFileNameFormatTextBox.FontStyle}" />
</Grid>
<Grid ColumnDefinitions="*,Auto">
<ComboBox Grid.Column="0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding PaidPostVariables}"
SelectedItem="{Binding SelectedPaidPostVariable}" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Insert Variable"
Command="{Binding InsertPaidPostVariableCommand}" />
</Grid>
<TextBlock IsVisible="{Binding HasUnknownPaidPostVariables}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding UnknownPaidPostVariablesMessage}"
TextWrapping="Wrap" />
<TextBlock IsVisible="{Binding HasPaidPostFileNameFormatError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding PaidPostFileNameFormatError}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel Spacing="8">
<TextBlock FontWeight="SemiBold" Foreground="{DynamicResource TextPrimaryBrush}"
Text="Free Message File Name Format" />
<Grid ClipToBounds="True">
<TextBox x:Name="MessageFileNameFormatTextBox"
Classes="fileNameOverlayInput"
Text="{Binding MessageFileNameFormat}"
Watermark="Optional: override global free message format"
Padding="8,6"
CaretBrush="{DynamicResource TextPrimaryBrush}" />
<controls:FileNameFormatOverlayTextBlock IsHitTestVisible="False"
Margin="{Binding #MessageFileNameFormatTextBox.Padding}"
VerticalAlignment="Center"
Segments="{Binding MessageSegments}"
SourceTextBox="{Binding #MessageFileNameFormatTextBox}"
FontFamily="{Binding #MessageFileNameFormatTextBox.FontFamily}"
FontSize="{Binding #MessageFileNameFormatTextBox.FontSize}"
FontWeight="{Binding #MessageFileNameFormatTextBox.FontWeight}"
FontStyle="{Binding #MessageFileNameFormatTextBox.FontStyle}" />
</Grid>
<Grid ColumnDefinitions="*,Auto">
<ComboBox Grid.Column="0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding MessageVariables}"
SelectedItem="{Binding SelectedMessageVariable}" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Insert Variable"
Command="{Binding InsertMessageVariableCommand}" />
</Grid>
<TextBlock IsVisible="{Binding HasUnknownMessageVariables}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding UnknownMessageVariablesMessage}"
TextWrapping="Wrap" />
<TextBlock IsVisible="{Binding HasMessageFileNameFormatError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding MessageFileNameFormatError}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel Spacing="8">
<TextBlock FontWeight="SemiBold" Foreground="{DynamicResource TextPrimaryBrush}"
Text="Paid Message File Name Format" />
<Grid ClipToBounds="True">
<TextBox x:Name="PaidMessageFileNameFormatTextBox"
Classes="fileNameOverlayInput"
Text="{Binding PaidMessageFileNameFormat}"
Watermark="Optional: override global paid message format"
Padding="8,6"
CaretBrush="{DynamicResource TextPrimaryBrush}" />
<controls:FileNameFormatOverlayTextBlock IsHitTestVisible="False"
Margin="{Binding #PaidMessageFileNameFormatTextBox.Padding}"
VerticalAlignment="Center"
Segments="{Binding PaidMessageSegments}"
SourceTextBox="{Binding #PaidMessageFileNameFormatTextBox}"
FontFamily="{Binding #PaidMessageFileNameFormatTextBox.FontFamily}"
FontSize="{Binding #PaidMessageFileNameFormatTextBox.FontSize}"
FontWeight="{Binding #PaidMessageFileNameFormatTextBox.FontWeight}"
FontStyle="{Binding #PaidMessageFileNameFormatTextBox.FontStyle}" />
</Grid>
<Grid ColumnDefinitions="*,Auto">
<ComboBox Grid.Column="0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding PaidMessageVariables}"
SelectedItem="{Binding SelectedPaidMessageVariable}" />
<Button Grid.Column="1"
Margin="8,0,0,0"
Classes="secondary"
Content="Insert Variable"
Command="{Binding InsertPaidMessageVariableCommand}" />
</Grid>
<TextBlock IsVisible="{Binding HasUnknownPaidMessageVariables}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding UnknownPaidMessageVariablesMessage}"
TextWrapping="Wrap" />
<TextBlock IsVisible="{Binding HasPaidMessageFileNameFormatError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding PaidMessageFileNameFormatError}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
<Button Content="Cancel"
Classes="secondary"
Command="{Binding CancelCommand}" />
<Button Content="Confirm"
Classes="primary"
Command="{Binding ConfirmCommand}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</Border>
</Grid>
<Grid Grid.Row="0" Grid.RowSpan="3"
IsVisible="{Binding IsSinglePostOrMessageModalOpen}"
Background="{DynamicResource OverlayBackgroundBrush}"
ZIndex="1001"
PointerPressed="OnModalOverlayClicked">
<Border Background="{DynamicResource ModalBackgroundBrush}"
BorderBrush="{DynamicResource ModalBorderBrush}"
BorderThickness="1"
CornerRadius="16"
Padding="32"
Width="760"
MaxHeight="700"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BoxShadow="0 20 25 -5 #19000000, 0 10 10 -5 #0F000000"
PointerPressed="OnModalContentClicked">
<ScrollViewer>
<StackPanel Spacing="18" Margin="8,4,8,4">
<TextBlock FontSize="20"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Download Single Post/Message" />
<TextBlock Foreground="{DynamicResource TextSecondaryBrush}"
TextWrapping="Wrap"
Text="Enter a post URL or paid message URL to download only that item." />
<Border Padding="16"
CornerRadius="10"
Background="{DynamicResource PreviewBackgroundBrush}"
BorderBrush="{DynamicResource PreviewBorderBrush}"
BorderThickness="1">
<StackPanel Spacing="14">
<TextBlock FontSize="15"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="How to find a URL" />
<!-- Post Instructions -->
<StackPanel Spacing="6">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Posts" />
<TextBlock Foreground="{DynamicResource TextSecondaryBrush}"
TextWrapping="Wrap"
Text="Click the ... menu on any post → 'Copy link to post'" />
</StackPanel>
<!-- Message Instructions -->
<StackPanel Spacing="6">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Messages (Paid Only)" />
<TextBlock Foreground="{DynamicResource TextSecondaryBrush}"
TextWrapping="Wrap"
Text="Go to main timeline → Purchased tab → Find message → Click ... menu → 'Copy link to message'" />
<TextBlock Foreground="{DynamicResource TextSecondaryBrush}"
FontStyle="Italic"
FontSize="12"
TextWrapping="Wrap"
Text="Note: Only unlocked PPV messages can be downloaded individually. For other messages, download all messages from the creator." />
</StackPanel>
</StackPanel>
</Border>
<StackPanel Spacing="6">
<TextBlock FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Post or Message URL" />
<TextBox Text="{Binding SinglePostOrMessageUrl}"
Watermark="https://onlyfans.com/... or https://onlyfans.com/my/chats/chat/.../?firstId=..." />
<TextBlock IsVisible="{Binding HasSinglePostOrMessageUrlError}"
Foreground="{DynamicResource ErrorTextBrush}"
Text="{Binding SinglePostOrMessageUrlError}"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
<Button Content="Cancel"
Classes="secondary"
Command="{Binding CancelSinglePostOrMessageCommand}" />
<Button Content="Download"
Classes="primary"
Command="{Binding SubmitSinglePostOrMessageCommand}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</Border>
</Grid>
<Grid Grid.Row="0" Grid.RowSpan="3"
IsVisible="{Binding IsDownloadSelectionWarningModalOpen}"
Background="{DynamicResource OverlayBackgroundBrush}"
ZIndex="1002"
PointerPressed="OnModalOverlayClicked">
<Border Background="{DynamicResource ModalBackgroundBrush}"
BorderBrush="{DynamicResource ModalBorderBrush}"
BorderThickness="1"
CornerRadius="16"
Padding="28"
Width="720"
MaxHeight="500"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BoxShadow="0 20 25 -5 #19000000, 0 10 10 -5 #0F000000"
PointerPressed="OnModalContentClicked">
<StackPanel Spacing="16">
<TextBlock FontSize="20"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="No Media Types/Sources Enabled" />
<TextBlock Foreground="{DynamicResource TextSecondaryBrush}"
TextWrapping="Wrap"
Text="{Binding DownloadSelectionWarningMessage}" />
<Grid ColumnDefinitions="*,Auto,Auto">
<Button Grid.Column="0"
Classes="secondary"
HorizontalAlignment="Left"
Content="Open Configuration"
Command="{Binding OpenConfigurationFromDownloadSelectionWarningCommand}" />
<Button Grid.Column="1"
Margin="10,0,0,0"
Content="Cancel"
Classes="secondary"
Command="{Binding CancelDownloadSelectionWarningCommand}" />
<Button Grid.Column="2"
Margin="10,0,0,0"
Content="Continue Anyways"
Classes="primary"
Command="{Binding ConfirmDownloadSelectionWarningCommand}" />
</Grid>
</StackPanel>
</Border>
</Grid>
<Grid Grid.Row="0" Grid.RowSpan="3"
IsVisible="{Binding IsMissingCdmWarningModalOpen}"
Background="{DynamicResource OverlayBackgroundBrush}"
ZIndex="1003"
PointerPressed="OnModalOverlayClicked">
<Border Background="{DynamicResource ModalBackgroundBrush}"
BorderBrush="{DynamicResource ModalBorderBrush}"
BorderThickness="1"
CornerRadius="16"
Padding="28"
Width="680"
MaxHeight="500"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BoxShadow="0 20 25 -5 #19000000, 0 10 10 -5 #0F000000"
PointerPressed="OnModalContentClicked">
<StackPanel Spacing="16">
<TextBlock FontSize="20"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimaryBrush}"
Text="Missing CDM Keys" />
<TextBlock Foreground="{DynamicResource TextSecondaryBrush}"
TextWrapping="Wrap"
Text="{Binding MissingCdmWarningMessage}" />
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
<Button Content="Cancel"
Classes="secondary"
Command="{Binding CancelMissingCdmWarningCommand}" />
<Button Content="Continue Download"
Classes="primary"
Command="{Binding ConfirmMissingCdmWarningCommand}" />
</StackPanel>
</StackPanel>
</Border>
</Grid>
<Border x:Name="CopyToastBorder"
Grid.Row="0"
Grid.RowSpan="3"
Classes="copyToast"
IsVisible="False"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,20,20"
ZIndex="2000">
<TextBlock x:Name="CopyToastTextBlock"
Foreground="{DynamicResource PrimaryButtonForegroundBrush}"
FontWeight="SemiBold"
Text="Copied to clipboard" />
</Border>
</Grid>
</Window>