Fix warnings

This commit is contained in:
whimsical-c4lic0 2026-02-17 01:14:07 -06:00
parent f4479a77ba
commit fccee9a520
6 changed files with 959 additions and 942 deletions

View File

@ -159,6 +159,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// Retrieves user information from the API. /// Retrieves user information from the API.
/// </summary> /// </summary>
/// <param name="endpoint">The user endpoint.</param> /// <param name="endpoint">The user endpoint.</param>
/// <param name="cancellationToken"></param>
/// <returns>The user entity when available.</returns> /// <returns>The user entity when available.</returns>
public async Task<UserEntities.User?> GetUserInfo(string endpoint, CancellationToken cancellationToken = default) public async Task<UserEntities.User?> GetUserInfo(string endpoint, CancellationToken cancellationToken = default)
{ {
@ -413,6 +414,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="endpoint">The endpoint to query.</param> /// <param name="endpoint">The endpoint to query.</param>
/// <param name="username">Optional username context.</param> /// <param name="username">Optional username context.</param>
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="cancellationToken"></param>
/// <returns>A mediaId-to-URL map.</returns> /// <returns>A mediaId-to-URL map.</returns>
public async Task<Dictionary<long, string>?> GetMedia(MediaType mediatype, public async Task<Dictionary<long, string>?> GetMedia(MediaType mediatype,
string endpoint, string endpoint,
@ -650,6 +652,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="username">The creator username.</param> /// <param name="username">The creator username.</param>
/// <param name="paidPostIds">A list to collect paid media IDs.</param> /// <param name="paidPostIds">A list to collect paid media IDs.</param>
/// <param name="statusReporter">Status reporter.</param> /// <param name="statusReporter">Status reporter.</param>
/// <param name="cancellationToken"></param>
/// <returns>A paid post collection.</returns> /// <returns>A paid post collection.</returns>
public async Task<PurchasedEntities.PaidPostCollection> GetPaidPosts(string endpoint, string folder, public async Task<PurchasedEntities.PaidPostCollection> GetPaidPosts(string endpoint, string folder,
string username, string username,
@ -832,6 +835,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="paidPostIds">Paid post media IDs to skip.</param> /// <param name="paidPostIds">Paid post media IDs to skip.</param>
/// <param name="statusReporter">Status reporter.</param> /// <param name="statusReporter">Status reporter.</param>
/// <param name="cancellationToken"></param>
/// <returns>A post collection.</returns> /// <returns>A post collection.</returns>
public async Task<PostEntities.PostCollection> GetPosts(string endpoint, string folder, List<long> paidPostIds, public async Task<PostEntities.PostCollection> GetPosts(string endpoint, string folder, List<long> paidPostIds,
IStatusReporter statusReporter, CancellationToken cancellationToken = default) IStatusReporter statusReporter, CancellationToken cancellationToken = default)
@ -1021,6 +1025,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// </summary> /// </summary>
/// <param name="endpoint">The post endpoint.</param> /// <param name="endpoint">The post endpoint.</param>
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="cancellationToken"></param>
/// <returns>A single post collection.</returns> /// <returns>A single post collection.</returns>
public async Task<SinglePostCollection> GetPost(string endpoint, string folder, CancellationToken cancellationToken = default) public async Task<SinglePostCollection> GetPost(string endpoint, string folder, CancellationToken cancellationToken = default)
{ {
@ -1169,6 +1174,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="paidPostIds">Paid post media IDs to skip.</param> /// <param name="paidPostIds">Paid post media IDs to skip.</param>
/// <param name="statusReporter">Status reporter.</param> /// <param name="statusReporter">Status reporter.</param>
/// <param name="cancellationToken"></param>
/// <returns>A streams collection.</returns> /// <returns>A streams collection.</returns>
public async Task<StreamEntities.StreamsCollection> GetStreams(string endpoint, string folder, public async Task<StreamEntities.StreamsCollection> GetStreams(string endpoint, string folder,
List<long> paidPostIds, List<long> paidPostIds,
@ -1321,6 +1327,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="endpoint">The archived posts endpoint.</param> /// <param name="endpoint">The archived posts endpoint.</param>
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="statusReporter">Status reporter.</param> /// <param name="statusReporter">Status reporter.</param>
/// <param name="cancellationToken"></param>
/// <returns>An archived collection.</returns> /// <returns>An archived collection.</returns>
public async Task<ArchivedEntities.ArchivedCollection> GetArchived(string endpoint, string folder, public async Task<ArchivedEntities.ArchivedCollection> GetArchived(string endpoint, string folder,
IStatusReporter statusReporter, CancellationToken cancellationToken = default) IStatusReporter statusReporter, CancellationToken cancellationToken = default)
@ -1475,6 +1482,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="endpoint">The messages endpoint.</param> /// <param name="endpoint">The messages endpoint.</param>
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="statusReporter">Status reporter.</param> /// <param name="statusReporter">Status reporter.</param>
/// <param name="cancellationToken"></param>
/// <returns>A message collection.</returns> /// <returns>A message collection.</returns>
public async Task<MessageEntities.MessageCollection> GetMessages(string endpoint, string folder, public async Task<MessageEntities.MessageCollection> GetMessages(string endpoint, string folder,
IStatusReporter statusReporter, CancellationToken cancellationToken = default) IStatusReporter statusReporter, CancellationToken cancellationToken = default)
@ -1664,6 +1672,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// </summary> /// </summary>
/// <param name="endpoint">The paid message endpoint.</param> /// <param name="endpoint">The paid message endpoint.</param>
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="cancellationToken"></param>
/// <returns>A single paid message collection.</returns> /// <returns>A single paid message collection.</returns>
public async Task<PurchasedEntities.SinglePaidMessageCollection> GetPaidMessage(string endpoint, string folder, CancellationToken cancellationToken = default) public async Task<PurchasedEntities.SinglePaidMessageCollection> GetPaidMessage(string endpoint, string folder, CancellationToken cancellationToken = default)
{ {
@ -1810,6 +1819,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="username">The creator username.</param> /// <param name="username">The creator username.</param>
/// <param name="statusReporter">Status reporter.</param> /// <param name="statusReporter">Status reporter.</param>
/// <param name="cancellationToken"></param>
/// <returns>A paid message collection.</returns> /// <returns>A paid message collection.</returns>
public async Task<PurchasedEntities.PaidMessageCollection> GetPaidMessages(string endpoint, string folder, public async Task<PurchasedEntities.PaidMessageCollection> GetPaidMessages(string endpoint, string folder,
string username, string username,
@ -2034,6 +2044,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// </summary> /// </summary>
/// <param name="endpoint">The purchased tab endpoint.</param> /// <param name="endpoint">The purchased tab endpoint.</param>
/// <param name="users">Known users map.</param> /// <param name="users">Known users map.</param>
/// <param name="cancellationToken"></param>
/// <returns>A username-to-userId map.</returns> /// <returns>A username-to-userId map.</returns>
public async Task<Dictionary<string, long>> GetPurchasedTabUsers(string endpoint, Dictionary<string, long> users, CancellationToken cancellationToken = default) public async Task<Dictionary<string, long>> GetPurchasedTabUsers(string endpoint, Dictionary<string, long> users, CancellationToken cancellationToken = default)
{ {
@ -2202,6 +2213,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="endpoint">The purchased tab endpoint.</param> /// <param name="endpoint">The purchased tab endpoint.</param>
/// <param name="folder">The base download folder.</param> /// <param name="folder">The base download folder.</param>
/// <param name="users">Known users map.</param> /// <param name="users">Known users map.</param>
/// <param name="cancellationToken"></param>
/// <returns>A list of purchased tab collections.</returns> /// <returns>A list of purchased tab collections.</returns>
public async Task<List<PurchasedEntities.PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder, public async Task<List<PurchasedEntities.PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder,
Dictionary<string, long> users, CancellationToken cancellationToken = default) Dictionary<string, long> users, CancellationToken cancellationToken = default)

View File

@ -36,7 +36,7 @@ internal sealed class AvaloniaDownloadEventHandler(
progressStart(description, maxValue, showSize); progressStart(description, maxValue, showSize);
try try
{ {
AvaloniaProgressReporter reporter = new(progressIncrement, isCancellationRequested, cancellationToken); AvaloniaProgressReporter reporter = new(progressIncrement, isCancellationRequested, CancellationToken);
return await work(reporter); return await work(reporter);
} }
finally finally

View File

@ -24,7 +24,8 @@ public partial class CreatorConfigEditorViewModel : ViewModelBase
public void LoadFromConfig(Dictionary<string, CreatorConfig> configs) public void LoadFromConfig(Dictionary<string, CreatorConfig> configs)
{ {
Rows.Clear(); Rows.Clear();
foreach (KeyValuePair<string, CreatorConfig> kvp in configs.OrderBy(c => c.Key, StringComparer.OrdinalIgnoreCase)) foreach (KeyValuePair<string, CreatorConfig> kvp in configs.OrderBy(c => c.Key,
StringComparer.OrdinalIgnoreCase))
{ {
Rows.Add(new CreatorConfigRowViewModel(kvp.Key, kvp.Value, OnDeleteRow, OnEditRow)); Rows.Add(new CreatorConfigRowViewModel(kvp.Key, kvp.Value, OnDeleteRow, OnEditRow));
} }
@ -37,6 +38,7 @@ public partial class CreatorConfigEditorViewModel : ViewModelBase
{ {
result[row.Username] = row.Config; result[row.Username] = row.Config;
} }
return result; return result;
} }
@ -53,24 +55,11 @@ public partial class CreatorConfigEditorViewModel : ViewModelBase
private void AddCreator() private void AddCreator()
{ {
Log.Information("AddCreator command executed"); Log.Information("AddCreator command executed");
Log.Information("ModalViewModel is null: {IsNull}", ModalViewModel == null);
_editingRow = null; _editingRow = null;
if (ModalViewModel != null)
{
Log.Information("Calling ModalViewModel.OpenForAdd()");
ModalViewModel.OpenForAdd(); ModalViewModel.OpenForAdd();
Log.Information("After OpenForAdd - Modal IsOpen: {IsOpen}", ModalViewModel.IsOpen);
}
else
{
Log.Error("ModalViewModel is null, cannot open modal");
}
} }
private void OnDeleteRow(CreatorConfigRowViewModel row) private void OnDeleteRow(CreatorConfigRowViewModel row) => Rows.Remove(row);
{
Rows.Remove(row);
}
private void OnEditRow(CreatorConfigRowViewModel row) private void OnEditRow(CreatorConfigRowViewModel row)
{ {

View File

@ -131,9 +131,9 @@ public partial class MainWindowViewModel(
private AppScreen _configReturnScreen = AppScreen.Loading; private AppScreen _configReturnScreen = AppScreen.Loading;
private bool _isApplyingListSelection; private bool _isApplyingListSelection;
public ObservableCollection<ConfigFieldViewModel> ConfigFields { get; } = []; private ObservableCollection<ConfigFieldViewModel> ConfigFields { get; } = [];
public ObservableCollection<ConfigCategoryViewModel> ConfigCategories { get; } = []; private static ObservableCollection<ConfigCategoryViewModel> ConfigCategories => [];
public ObservableCollection<ConfigCategoryViewModel> ConfigCategoriesLeft { get; } = []; public ObservableCollection<ConfigCategoryViewModel> ConfigCategoriesLeft { get; } = [];
@ -224,9 +224,12 @@ public partial class MainWindowViewModel(
public bool HasMediaSourcesError => !string.IsNullOrWhiteSpace(MediaSourcesError); public bool HasMediaSourcesError => !string.IsNullOrWhiteSpace(MediaSourcesError);
public string FfmpegPathDisplay => HidePrivateInfo && !string.IsNullOrWhiteSpace(FfmpegPath) ? "[Hidden for Privacy]" : FfmpegPath; public string FfmpegPathDisplay =>
HidePrivateInfo && !string.IsNullOrWhiteSpace(FfmpegPath) ? "[Hidden for Privacy]" : FfmpegPath;
public string DownloadPathDisplay => HidePrivateInfo && !string.IsNullOrWhiteSpace(DownloadPath) ? "[Hidden for Privacy]" : DownloadPath; public string DownloadPathDisplay => HidePrivateInfo && !string.IsNullOrWhiteSpace(DownloadPath)
? "[Hidden for Privacy]"
: DownloadPath;
public string FfmpegPathHelpText => GetConfigHelpText(nameof(Config.FFmpegPath)); public string FfmpegPathHelpText => GetConfigHelpText(nameof(Config.FFmpegPath));
@ -310,7 +313,9 @@ public partial class MainWindowViewModel(
{ {
string normalizedPath = NormalizePathForDisplay(path); string normalizedPath = NormalizePathForDisplay(path);
_actualFfmpegPath = normalizedPath; _actualFfmpegPath = normalizedPath;
FfmpegPath = HidePrivateInfo && !string.IsNullOrWhiteSpace(normalizedPath) ? "[Hidden for Privacy]" : normalizedPath; FfmpegPath = HidePrivateInfo && !string.IsNullOrWhiteSpace(normalizedPath)
? "[Hidden for Privacy]"
: normalizedPath;
FfmpegPathError = string.Empty; FfmpegPathError = string.Empty;
} }
@ -318,7 +323,9 @@ public partial class MainWindowViewModel(
{ {
string normalizedPath = NormalizePathForDisplay(path); string normalizedPath = NormalizePathForDisplay(path);
_actualDownloadPath = normalizedPath; _actualDownloadPath = normalizedPath;
DownloadPath = HidePrivateInfo && !string.IsNullOrWhiteSpace(normalizedPath) ? "[Hidden for Privacy]" : normalizedPath; DownloadPath = HidePrivateInfo && !string.IsNullOrWhiteSpace(normalizedPath)
? "[Hidden for Privacy]"
: normalizedPath;
DownloadPathError = string.Empty; DownloadPathError = string.Empty;
} }
@ -475,21 +482,7 @@ public partial class MainWindowViewModel(
private void AddCreatorConfig() private void AddCreatorConfig()
{ {
Log.Information("=== AddCreatorConfig command called ==="); Log.Information("=== AddCreatorConfig command called ===");
Log.Information("CreatorConfigEditor is null: {IsNull}", CreatorConfigEditor == null);
if (CreatorConfigEditor != null)
{
Log.Information("CreatorConfigEditor.AddCreatorCommand is null: {IsNull}", CreatorConfigEditor.AddCreatorCommand == null);
Log.Information("ModalViewModel is null: {IsNull}", CreatorConfigEditor.ModalViewModel == null);
if (CreatorConfigEditor.ModalViewModel != null)
{
Log.Information("ModalViewModel.IsOpen before: {IsOpen}", CreatorConfigEditor.ModalViewModel.IsOpen);
}
CreatorConfigEditor.AddCreatorCommand.Execute(null); CreatorConfigEditor.AddCreatorCommand.Execute(null);
if (CreatorConfigEditor.ModalViewModel != null)
{
Log.Information("ModalViewModel.IsOpen after: {IsOpen}", CreatorConfigEditor.ModalViewModel.IsOpen);
}
}
} }
[RelayCommand] [RelayCommand]
@ -625,14 +618,15 @@ public partial class MainWindowViewModel(
0, 0,
false); false);
CancellationTokenSource cancellationSource = _workCancellationSource;
AvaloniaDownloadEventHandler eventHandler = new( AvaloniaDownloadEventHandler eventHandler = new(
AppendLog, AppendLog,
UpdateProgressStatus, UpdateProgressStatus,
StartDownloadProgress, StartDownloadProgress,
IncrementDownloadProgress, IncrementDownloadProgress,
StopDownloadProgress, StopDownloadProgress,
() => _workCancellationSource?.IsCancellationRequested == true, () => cancellationSource.IsCancellationRequested,
_workCancellationSource.Token); cancellationSource.Token);
try try
{ {
@ -762,6 +756,7 @@ public partial class MainWindowViewModel(
{ {
_actualFfmpegPath = value; _actualFfmpegPath = value;
} }
FfmpegPathError = string.Empty; FfmpegPathError = string.Empty;
} }
@ -771,6 +766,7 @@ public partial class MainWindowViewModel(
{ {
_actualDownloadPath = value; _actualDownloadPath = value;
} }
DownloadPathError = string.Empty; DownloadPathError = string.Empty;
} }
@ -936,7 +932,7 @@ public partial class MainWindowViewModel(
UpdateUserListsCollection(); UpdateUserListsCollection();
UpdateIgnoredUsersListFieldOptions(); UpdateIgnoredUsersListFieldOptions();
CreatorConfigEditor?.UpdateAvailableUsers(_allUsers.Keys); CreatorConfigEditor.UpdateAvailableUsers(_allUsers.Keys);
SelectedListName = null; SelectedListName = null;
@ -1100,8 +1096,8 @@ public partial class MainWindowViewModel(
private void UpdateIgnoredUsersListFieldOptions() private void UpdateIgnoredUsersListFieldOptions()
{ {
IEnumerable<string> listNames = _allLists.Keys List<string> listNames = _allLists.Keys
.OrderBy(listName => listName, StringComparer.OrdinalIgnoreCase); .OrderBy(listName => listName, StringComparer.OrdinalIgnoreCase).ToList();
foreach (ConfigFieldViewModel field in ConfigFields.Where(field => field.IsIgnoredUsersListField)) foreach (ConfigFieldViewModel field in ConfigFields.Where(field => field.IsIgnoredUsersListField))
{ {
@ -1128,7 +1124,9 @@ public partial class MainWindowViewModel(
string downloadPath = ResolveDownloadPathForDisplay(config.DownloadPath); string downloadPath = ResolveDownloadPathForDisplay(config.DownloadPath);
_actualDownloadPath = downloadPath; _actualDownloadPath = downloadPath;
DownloadPath = HidePrivateInfo && !string.IsNullOrWhiteSpace(downloadPath) ? "[Hidden for Privacy]" : downloadPath; DownloadPath = HidePrivateInfo && !string.IsNullOrWhiteSpace(downloadPath)
? "[Hidden for Privacy]"
: downloadPath;
ClearSpecialConfigErrors(); ClearSpecialConfigErrors();

View File

@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:OF_DL.Gui.ViewModels" xmlns:vm="using:OF_DL.Gui.ViewModels"
xmlns:views="using:OF_DL.Gui.Views"
x:Class="OF_DL.Gui.Views.MainWindow" x:Class="OF_DL.Gui.Views.MainWindow"
x:DataType="vm:MainWindowViewModel" x:DataType="vm:MainWindowViewModel"
Width="1320" Width="1320"
@ -252,8 +253,7 @@
Text="{Binding CategoryName}" /> Text="{Binding CategoryName}" />
<StackPanel IsVisible="{Binding IsDownloadBehavior}" <StackPanel IsVisible="{Binding IsDownloadBehavior}"
Spacing="4" Spacing="4"
Margin="0,0,0,10" Margin="0,0,0,10">
x:CompileBindings="False">
<StackPanel Orientation="Horizontal" Spacing="6"> <StackPanel Orientation="Horizontal" Spacing="6">
<TextBlock FontWeight="SemiBold" <TextBlock FontWeight="SemiBold"
Foreground="#1F2A44" Foreground="#1F2A44"
@ -272,13 +272,13 @@
BorderThickness="1" BorderThickness="1"
CornerRadius="10" CornerRadius="10"
Content="?" Content="?"
ToolTip.Tip="{Binding DataContext.DownloadPathHelpText, RelativeSource={RelativeSource AncestorType=Window}}" /> ToolTip.Tip="{Binding ViewModel.DownloadPathHelpText, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}" />
</StackPanel> </StackPanel>
<Grid ColumnDefinitions="*,Auto"> <Grid ColumnDefinitions="*,Auto">
<TextBox Grid.Column="0" <TextBox Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding DataContext.DownloadPath, RelativeSource={RelativeSource AncestorType=Window}}" Text="{Binding ViewModel.DownloadPath, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
Watermark="Select download folder" /> Watermark="Select download folder" />
<Button Grid.Column="1" <Button Grid.Column="1"
Margin="8,0,0,0" Margin="8,0,0,0"
@ -287,9 +287,9 @@
Click="OnBrowseDownloadPathClick" /> Click="OnBrowseDownloadPathClick" />
</Grid> </Grid>
<TextBlock <TextBlock
IsVisible="{Binding DataContext.HasDownloadPathError, RelativeSource={RelativeSource AncestorType=Window}}" IsVisible="{Binding ViewModel.HasDownloadPathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=False}"
Foreground="#FF5A5A" Foreground="#FF5A5A"
Text="{Binding DataContext.DownloadPathError, RelativeSource={RelativeSource AncestorType=Window}}" Text="{Binding ViewModel.DownloadPathError, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue=''}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</StackPanel> </StackPanel>
<StackPanel IsVisible="{Binding HasSpecificDateFilterFields}" <StackPanel IsVisible="{Binding HasSpecificDateFilterFields}"
@ -305,7 +305,8 @@
Text="Download Posts from Specific Dates" Text="Download Posts from Specific Dates"
VerticalAlignment="Center" VerticalAlignment="Center"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<Button IsVisible="{Binding HasSpecificDateFilterHelpText}" <Button
IsVisible="{Binding HasSpecificDateFilterHelpText}"
Width="20" Width="20"
Height="20" Height="20"
MinWidth="20" MinWidth="20"
@ -328,19 +329,19 @@
Content="Enable" Content="Enable"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
IsChecked="{Binding DownloadOnlySpecificDatesField.BoolValue}" /> IsChecked="{Binding DownloadOnlySpecificDatesField.BoolValue, FallbackValue=False}" />
<ComboBox Grid.Column="1" <ComboBox Grid.Column="1"
Width="140" Width="140"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
IsEnabled="{Binding DownloadOnlySpecificDatesField.BoolValue}" IsEnabled="{Binding DownloadOnlySpecificDatesField.BoolValue, FallbackValue=False}"
ItemsSource="{Binding DownloadDateSelectionField.EnumOptions}" ItemsSource="{Binding DownloadDateSelectionField.EnumOptions, FallbackValue={x:Null}}"
SelectedItem="{Binding DownloadDateSelectionField.EnumValue}" /> SelectedItem="{Binding DownloadDateSelectionField.EnumValue, FallbackValue={x:Null}}" />
<DatePicker Grid.Column="2" <DatePicker Grid.Column="2"
MinWidth="200" MinWidth="200"
VerticalAlignment="Center" VerticalAlignment="Center"
IsEnabled="{Binding DownloadOnlySpecificDatesField.BoolValue}" IsEnabled="{Binding DownloadOnlySpecificDatesField.BoolValue, FallbackValue=False}"
SelectedDate="{Binding CustomDateField.DateValue}" /> SelectedDate="{Binding CustomDateField.DateValue, FallbackValue={x:Null}}" />
</Grid> </Grid>
</StackPanel> </StackPanel>
<Grid IsVisible="{Binding HasRateLimitFields}" <Grid IsVisible="{Binding HasRateLimitFields}"
@ -383,10 +384,10 @@
Spacing="8" Spacing="8"
VerticalAlignment="Center"> VerticalAlignment="Center">
<CheckBox Content="Enable" <CheckBox Content="Enable"
IsChecked="{Binding LimitDownloadRateField.BoolValue}" /> IsChecked="{Binding LimitDownloadRateField.BoolValue, FallbackValue=False}" />
<NumericUpDown MinWidth="120" <NumericUpDown MinWidth="120"
IsEnabled="{Binding LimitDownloadRateField.BoolValue}" IsEnabled="{Binding LimitDownloadRateField.BoolValue, FallbackValue=False}"
Value="{Binding DownloadLimitInMbPerSecField.NumericValue}" Value="{Binding DownloadLimitInMbPerSecField.NumericValue, FallbackValue=0}"
Increment="1" Increment="1"
FormatString="N0" /> FormatString="N0" />
<TextBlock Text="Mbps" <TextBlock Text="Mbps"
@ -431,13 +432,13 @@
</Grid> </Grid>
<StackPanel Grid.Column="1" Spacing="6"> <StackPanel Grid.Column="1" Spacing="6">
<CheckBox Content="Paid Posts" <CheckBox Content="Paid Posts"
IsChecked="{Binding FolderPerPaidPostField.BoolValue}" /> IsChecked="{Binding FolderPerPaidPostField.BoolValue, FallbackValue=False}" />
<CheckBox Content="Free Posts" <CheckBox Content="Free Posts"
IsChecked="{Binding FolderPerPostField.BoolValue}" /> IsChecked="{Binding FolderPerPostField.BoolValue, FallbackValue=False}" />
<CheckBox Content="Paid Messages" <CheckBox Content="Paid Messages"
IsChecked="{Binding FolderPerPaidMessageField.BoolValue}" /> IsChecked="{Binding FolderPerPaidMessageField.BoolValue, FallbackValue=False}" />
<CheckBox Content="Free Messages" <CheckBox Content="Free Messages"
IsChecked="{Binding FolderPerMessageField.BoolValue}" /> IsChecked="{Binding FolderPerMessageField.BoolValue, FallbackValue=False}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
<ItemsControl ItemsSource="{Binding Fields}"> <ItemsControl ItemsSource="{Binding Fields}">
@ -502,7 +503,8 @@
Increment="1" Increment="1"
FormatString="N0" /> FormatString="N0" />
<StackPanel IsVisible="{Binding IsTimeoutField}" <StackPanel
IsVisible="{Binding IsTimeoutField}"
Orientation="Horizontal" Orientation="Horizontal"
Spacing="8"> Spacing="8">
<NumericUpDown MinWidth="120" <NumericUpDown MinWidth="120"
@ -515,14 +517,16 @@
VerticalAlignment="Center" /> VerticalAlignment="Center" />
</StackPanel> </StackPanel>
<TextBox IsVisible="{Binding IsRegularTextInput}" <TextBox
IsVisible="{Binding IsRegularTextInput}"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
AcceptsReturn="{Binding IsMultiline}" AcceptsReturn="{Binding IsMultiline}"
TextWrapping="Wrap" TextWrapping="Wrap"
MinHeight="{Binding TextBoxMinHeight}" MinHeight="{Binding TextBoxMinHeight}"
Text="{Binding TextValue}" /> Text="{Binding TextValue}" />
<Grid IsVisible="{Binding IsIgnoredUsersListField}" <Grid x:Name="IgnoredUsersListGrid"
IsVisible="{Binding IsIgnoredUsersListField}"
ColumnDefinitions="*,Auto" ColumnDefinitions="*,Auto"
x:CompileBindings="False"> x:CompileBindings="False">
<ComboBox Grid.Column="0" <ComboBox Grid.Column="0"
@ -554,7 +558,7 @@
CornerRadius="8" CornerRadius="8"
Content="⟳" Content="⟳"
ToolTip.Tip="Refresh list names from OnlyFans" ToolTip.Tip="Refresh list names from OnlyFans"
Command="{Binding DataContext.RefreshIgnoredUsersListsCommand, RelativeSource={RelativeSource AncestorType=Window}}" Command="{Binding ViewModel.RefreshIgnoredUsersListsCommand, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue={x:Null}}"
CommandParameter="{Binding}" /> CommandParameter="{Binding}" />
</Grid> </Grid>
@ -607,39 +611,48 @@
</StackPanel> </StackPanel>
<StackPanel IsVisible="{Binding IsCreatorConfigsField}" <StackPanel
Spacing="6" IsVisible="{Binding IsCreatorConfigsField}"
x:CompileBindings="False"> Spacing="6">
<Button Classes="secondary" <Button Classes="secondary"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Command="{Binding DataContext.AddCreatorConfigCommand, RelativeSource={RelativeSource AncestorType=Window}}"> Command="{Binding ViewModel.AddCreatorConfigCommand, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue={x:Null}}">
<StackPanel Orientation="Horizontal" Spacing="6"> <StackPanel
<TextBlock Text="+" FontWeight="Bold" /> Orientation="Horizontal"
Spacing="6">
<TextBlock Text="+"
FontWeight="Bold" />
<TextBlock Text="Add Creator" /> <TextBlock Text="Add Creator" />
</StackPanel> </StackPanel>
</Button> </Button>
<ScrollViewer MaxHeight="264"> <ScrollViewer MaxHeight="264">
<ItemsControl ItemsSource="{Binding DataContext.CreatorConfigEditor.Rows, RelativeSource={RelativeSource AncestorType=Window}}"> <ItemsControl
ItemsSource="{Binding ViewModel.CreatorConfigEditor.Rows, RelativeSource={RelativeSource AncestorType=views:MainWindow}, FallbackValue={x:Null}}">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Spacing="6" /> <StackPanel Spacing="6" />
</ItemsPanelTemplate> </ItemsPanelTemplate>
</ItemsControl.ItemsPanel> </ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:CreatorConfigRowViewModel"> <DataTemplate
<Border Background="#F5F8FE" x:DataType="vm:CreatorConfigRowViewModel">
<Border
Background="#F5F8FE"
BorderBrush="#D8E3F4" BorderBrush="#D8E3F4"
BorderThickness="1" BorderThickness="1"
CornerRadius="8" CornerRadius="8"
Padding="10"> Padding="10">
<Grid ColumnDefinitions="*,Auto,Auto"> <Grid
<TextBlock Grid.Column="0" ColumnDefinitions="*,Auto,Auto">
<TextBlock
Grid.Column="0"
FontWeight="SemiBold" FontWeight="SemiBold"
Foreground="#1F2A44" Foreground="#1F2A44"
Text="{Binding Username}" Text="{Binding Username}"
VerticalAlignment="Center" /> VerticalAlignment="Center" />
<Button Grid.Column="1" <Button
Grid.Column="1"
Width="28" Width="28"
Height="28" Height="28"
MinWidth="28" MinWidth="28"
@ -657,7 +670,8 @@
Content="✎" Content="✎"
ToolTip.Tip="Edit" ToolTip.Tip="Edit"
Command="{Binding EditCommand}" /> Command="{Binding EditCommand}" />
<Button Grid.Column="2" <Button
Grid.Column="2"
Width="28" Width="28"
Height="28" Height="28"
MinWidth="28" MinWidth="28"
@ -735,7 +749,8 @@
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<Grid IsVisible="{Binding IsUserSelectionScreen}" RowDefinitions="Auto,*,Auto" ColumnDefinitions="2*,3*"> <Grid IsVisible="{Binding IsUserSelectionScreen}" RowDefinitions="Auto,*,Auto"
ColumnDefinitions="2*,3*">
<Border Grid.Row="0" <Border Grid.Row="0"
Grid.ColumnSpan="2" Grid.ColumnSpan="2"
Padding="10" Padding="10"
@ -784,7 +799,8 @@
SelectedItem="{Binding SelectedListName}" SelectedItem="{Binding SelectedListName}"
IsEnabled="{Binding !IsDownloading}" /> IsEnabled="{Binding !IsDownloading}" />
</Grid> </Grid>
<ListBox Grid.Row="1" Margin="0,8,0,0" ItemsSource="{Binding AvailableUsers}" IsEnabled="{Binding !IsDownloading}"> <ListBox Grid.Row="1" Margin="0,8,0,0" ItemsSource="{Binding AvailableUsers}"
IsEnabled="{Binding !IsDownloading}">
<ListBox.Styles> <ListBox.Styles>
<Style Selector="ListBoxItem"> <Style Selector="ListBoxItem">
<Setter Property="Padding" Value="0" /> <Setter Property="Padding" Value="0" />
@ -811,7 +827,7 @@
</Border> </Border>
<Border Grid.Row="2" <Border Grid.Row="2"
Grid.ColumnSpan="2" Grid.ColumnSpan="2" Grid.Column="0"
Margin="0,10,0,0" Margin="0,10,0,0"
Padding="10" Padding="10"
Classes="surface" Classes="surface"
@ -845,7 +861,7 @@
</Grid> </Grid>
<!-- Modal Overlay --> <!-- Modal Overlay -->
<Grid Grid.RowSpan="3" <Grid Grid.Row="0" Grid.RowSpan="3"
IsVisible="{Binding CreatorConfigEditor.ModalViewModel.IsOpen}" IsVisible="{Binding CreatorConfigEditor.ModalViewModel.IsOpen}"
Background="#80000000" Background="#80000000"
ZIndex="1000" ZIndex="1000"
@ -1069,3 +1085,4 @@
</Grid> </Grid>
</Grid> </Grid>
</Window> </Window>

View File

@ -11,6 +11,7 @@ namespace OF_DL.Gui.Views;
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
private bool _hasInitialized; private bool _hasInitialized;
public MainWindowViewModel? ViewModel => DataContext as MainWindowViewModel;
public MainWindow() public MainWindow()
{ {