- Updated `IMediaSourceCatalog` to support user-added media sources, allowing dynamic editing and management of sources. - Removed the `UrlListSource` class as its functionality is now integrated into the new catalog structure. - Enhanced `CollectOptions` to default `RequireProxy` to true, ensuring stricter handling of proxy requirements. - Improved error handling in `ParseError` to include a `Subject` field for better context on failures. - Adjusted dependency injection to reflect changes in media source management, removing old source registrations. - Introduced background proxy checks to ensure a more robust proxy pool management during collection processes. These changes streamline the media collection process and improve the overall user experience by providing clearer error reporting and more flexible source management.
81 lines
3.3 KiB
C#
81 lines
3.3 KiB
C#
using AvParser.Core.Collecting;
|
|
using AvParser.Core.Collecting.Sources;
|
|
using AvParser.UI.Localization;
|
|
using ReactiveUI;
|
|
|
|
namespace AvParser.UI.ViewModels;
|
|
|
|
/// <summary>A media source paired with its translated name and description.</summary>
|
|
/// <remarks>
|
|
/// The domain knows nothing about languages, so <see cref="IMediaSource"/> carries English text.
|
|
/// This looks the id up as <c>Source.{id}.Name</c> and falls back to what the source itself says —
|
|
/// which is what user-added sources always do, since their name is data the user typed, not a resx
|
|
/// key. Disposable because the catalog rebuilds these on every edit, and each one holds a
|
|
/// language-changed subscription that would otherwise leak.
|
|
/// </remarks>
|
|
public sealed class MediaSourceViewModel : ReactiveObject, IDisposable
|
|
{
|
|
private bool _isSelected;
|
|
|
|
/// <summary>Wraps a source.</summary>
|
|
public MediaSourceViewModel(IMediaSource source)
|
|
{
|
|
Source = source ?? throw new ArgumentNullException(nameof(source));
|
|
Localizer.Instance.LanguageChanged += OnLanguageChanged;
|
|
}
|
|
|
|
/// <summary>Whether the next run includes this source.</summary>
|
|
/// <remarks>
|
|
/// Ticking is what a run acts on; the list's highlight only says which source the editor,
|
|
/// the delete button and the purge button are aimed at. Keeping the two apart is what lets a
|
|
/// run cover five sources while the user edits a sixth.
|
|
/// </remarks>
|
|
public bool IsSelected
|
|
{
|
|
get => _isSelected;
|
|
set => this.RaiseAndSetIfChanged(ref _isSelected, value);
|
|
}
|
|
|
|
/// <summary>The source itself.</summary>
|
|
public IMediaSource Source { get; }
|
|
|
|
/// <summary>The config behind the source, when it is a pattern source (they all are today).</summary>
|
|
public PatternSourceConfig? Config => (Source as PatternMediaSource)?.Config;
|
|
|
|
/// <summary>Stable identifier.</summary>
|
|
public string Id => Source.Id;
|
|
|
|
/// <summary>Translated name, or the source's own when untranslated.</summary>
|
|
public string Name => Localizer.Instance.GetOrDefault($"Source.{Id}.Name", Source.DisplayName);
|
|
|
|
/// <summary>Translated description, or the source's own when untranslated.</summary>
|
|
public string Description => Localizer.Instance.GetOrDefault($"Source.{Id}.Description", Source.Description);
|
|
|
|
/// <summary>Whether this source goes to the network at all.</summary>
|
|
public bool RequiresNetwork => Source.RequiresNetwork;
|
|
|
|
/// <summary>
|
|
/// Whether this source may run from the user's own address when no proxy is live.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Anything that is not a configured pattern source answers <see langword="false"/>: the safe
|
|
/// end, since a source with nowhere to say otherwise has not said otherwise.
|
|
/// </remarks>
|
|
public bool AllowsDirectConnection => Config?.AllowDirectConnection ?? false;
|
|
|
|
/// <summary>Whether a run including this source is gated on a live proxy.</summary>
|
|
public bool NeedsProxy => RequiresNetwork && !AllowsDirectConnection;
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString() => Name;
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose() => Localizer.Instance.LanguageChanged -= OnLanguageChanged;
|
|
|
|
private void OnLanguageChanged(object? sender, EventArgs e)
|
|
{
|
|
this.RaisePropertyChanged(nameof(Name));
|
|
this.RaisePropertyChanged(nameof(Description));
|
|
}
|
|
}
|