From ac1c8146334dae983dace5ae613c00e76cfe0412 Mon Sep 17 00:00:00 2001 From: whimsical-c4lic0 Date: Tue, 17 Feb 2026 17:14:45 -0600 Subject: [PATCH] Add help links and pages --- AGENTS.md | 3 +- OF DL.Gui/ViewModels/MainWindowViewModel.cs | 39 ++++- OF DL.Gui/Views/AboutWindow.axaml | 103 ++++++++++++ OF DL.Gui/Views/AboutWindow.axaml.cs | 64 ++++++++ OF DL.Gui/Views/FaqWindow.axaml | 107 +++++++++++++ OF DL.Gui/Views/FaqWindow.axaml.cs | 167 ++++++++++++++++++++ OF DL.Gui/Views/MainWindow.axaml | 120 ++++++++------ OF DL.Gui/Views/MainWindow.axaml.cs | 40 +++++ docs/running-the-program.md | 7 + 9 files changed, 594 insertions(+), 56 deletions(-) create mode 100644 OF DL.Gui/Views/AboutWindow.axaml create mode 100644 OF DL.Gui/Views/AboutWindow.axaml.cs create mode 100644 OF DL.Gui/Views/FaqWindow.axaml create mode 100644 OF DL.Gui/Views/FaqWindow.axaml.cs diff --git a/AGENTS.md b/AGENTS.md index a2f6d1a..c4f4876 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ most important change points. - `OF DL/Program.cs` is the single entrypoint and routes between GUI (default) and CLI (`--cli`). - `OF DL/CLI/` contains Spectre.Console UI helpers and progress reporting (CLI-only). -- `OF DL.Gui/` contains the Avalonia desktop UI (`App`, `MainWindow`, MVVM view models, and GUI event handlers). +- `OF DL.Gui/` contains the Avalonia desktop UI (`App`, `MainWindow`, `AboutWindow`, `FaqWindow`, MVVM view models, and GUI event handlers). - `OF DL.Core/Services/` contains application services (API, auth, download, config, DB, startup, logging, filenames). - `OF DL.Core/Models/` holds configuration, auth, API request/response models, downloads/startup results, DTOs, entities, and mapping helpers. @@ -232,6 +232,7 @@ cookies/user-agent. Output is written to `{filename}_source.mp4`, then moved and - `OF DL/Program.cs` for the execution path and menu flow. - `OF DL.Gui/ViewModels/MainWindowViewModel.cs` for GUI startup flow (config -> auth -> users/lists -> selection). - `OF DL.Gui/Views/MainWindow.axaml` for GUI layout and interaction points. +- `OF DL.Gui/Views/AboutWindow.axaml` and `OF DL.Gui/Views/FaqWindow.axaml` for Help menu windows. - `OF DL.Core/Services/ApiService.cs` for OF API calls and header signing. - `OF DL.Core/Services/DownloadService.cs` for downloads and DRM handling. - `OF DL.Core/Services/DownloadOrchestrationService.cs` for creator selection and flow control. diff --git a/OF DL.Gui/ViewModels/MainWindowViewModel.cs b/OF DL.Gui/ViewModels/MainWindowViewModel.cs index 9acbc6c..2aafb5d 100644 --- a/OF DL.Gui/ViewModels/MainWindowViewModel.cs +++ b/OF DL.Gui/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,6 @@ using System.Collections.ObjectModel; using System.ComponentModel; +using System.Reflection; using System.Text.RegularExpressions; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; @@ -26,9 +27,13 @@ public partial class MainWindowViewModel( IStartupService startupService, IDownloadOrchestrationService downloadOrchestrationService) : ViewModelBase { + private const string UnknownToolVersion = "Not detected"; + private static readonly string s_defaultDownloadPath = Path.GetFullPath( Path.Combine(Directory.GetCurrentDirectory(), "__user_data__", "sites", "OnlyFans")); + private static readonly string s_programVersion = ResolveProgramVersion(); + private static readonly (string DisplayName, string PropertyName)[] s_mediaTypeOptions = [ ("Videos", nameof(Config.DownloadVideos)), @@ -266,6 +271,16 @@ public partial class MainWindowViewModel( public bool HidePrivateInfo { get; } = Program.HidePrivateInfo; + public string ProgramVersion => s_programVersion; + + public string FfmpegVersion => string.IsNullOrWhiteSpace(_startupResult.FfmpegVersion) + ? UnknownToolVersion + : _startupResult.FfmpegVersion; + + public string FfprobeVersion => string.IsNullOrWhiteSpace(_startupResult.FfprobeVersion) + ? UnknownToolVersion + : _startupResult.FfprobeVersion; + [ObservableProperty] private string? _selectedListName; [ObservableProperty] private bool _hasInitialized; @@ -473,6 +488,11 @@ public partial class MainWindowViewModel( [RelayCommand] private void EditConfig() { + if (CurrentScreen == AppScreen.Config) + { + return; + } + _configReturnScreen = CurrentScreen; BuildConfigFields(configService.CurrentConfig); ConfigScreenMessage = "Edit configuration values and save to apply changes."; @@ -958,6 +978,8 @@ public partial class MainWindowViewModel( { SetLoading("Validating environment..."); _startupResult = await startupService.ValidateEnvironmentAsync(); + OnPropertyChanged(nameof(FfmpegVersion)); + OnPropertyChanged(nameof(FfprobeVersion)); if (!_startupResult.IsWindowsVersionValid) { @@ -1172,13 +1194,13 @@ public partial class MainWindowViewModel( CreatorConfigEditor = new CreatorConfigEditorViewModel(_allUsers.Keys); CreatorConfigEditor.LoadFromConfig(config.CreatorConfigs); - IEnumerable properties = typeof(Config) + IEnumerable properties = typeof(Config) .GetProperties() .Where(property => property.CanRead && property.CanWrite) .Where(property => !IsHiddenConfigField(property.Name)) .OrderBy(property => property.Name); - foreach (System.Reflection.PropertyInfo property in properties) + foreach (PropertyInfo property in properties) { object? value = property.GetValue(config); IEnumerable ignoredUsersListNames = property.Name == nameof(Config.IgnoredUsersListName) @@ -1300,7 +1322,7 @@ public partial class MainWindowViewModel( private static bool GetBooleanConfigValue(Config config, string propertyName) { - System.Reflection.PropertyInfo? property = typeof(Config).GetProperty(propertyName); + PropertyInfo? property = typeof(Config).GetProperty(propertyName); if (property == null) { return false; @@ -1341,7 +1363,7 @@ public partial class MainWindowViewModel( { foreach (MultiSelectOptionViewModel option in options) { - System.Reflection.PropertyInfo? property = typeof(Config).GetProperty(option.PropertyName); + PropertyInfo? property = typeof(Config).GetProperty(option.PropertyName); if (property?.PropertyType == typeof(bool)) { property.SetValue(config, option.IsSelected); @@ -1404,6 +1426,15 @@ public partial class MainWindowViewModel( private static string EscapePathForConfig(string path) => path.Replace(@"\", @"\\"); + private static string ResolveProgramVersion() + { + Version? version = Assembly.GetEntryAssembly()?.GetName().Version + ?? typeof(MainWindowViewModel).Assembly.GetName().Version; + return version == null + ? "Unknown" + : $"{version.Major}.{version.Minor}.{version.Build}"; + } + private static void ApplyConfiguredTheme(Theme theme) { if (Application.Current == null) diff --git a/OF DL.Gui/Views/AboutWindow.axaml b/OF DL.Gui/Views/AboutWindow.axaml new file mode 100644 index 0000000..987473f --- /dev/null +++ b/OF DL.Gui/Views/AboutWindow.axaml @@ -0,0 +1,103 @@ + + + + + + + + + + +