using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using VideoDownloader.Core.Detection; using VideoDownloader.Core.Social; namespace VideoDownloader.App.ViewModels; public class DownloadItemViewModel : INotifyPropertyChanged { private string _status = "대기"; private int _progress; private bool _isIndeterminate; private string _segments = ""; private string? _outputPath; private string? _error; private FormatOption? _selectedFormat; private bool _isFetchingFormats; private string _title; public string Title { get => _title; set => SetField(ref _title, value); } public string FormatTag { get; init; } = "FILE"; // 다운로드 실행에 필요한 컨텍스트 (감지 시 고정) public MediaKind Kind { get; init; } public Uri MediaUrl { get; init; } = null!; public string OutputBase { get; set; } = ""; public string? PageUrl { get; init; } public string? ContentType { get; init; } // 소셜(YouTube/Instagram/X) 카드: 화질/형식 선택 public bool IsSocial => Kind == MediaKind.Social; public ObservableCollection Formats { get; } = new(); public FormatOption? SelectedFormat { get => _selectedFormat; set => SetField(ref _selectedFormat, value); } public bool IsFetchingFormats { get => _isFetchingFormats; set => SetField(ref _isFetchingFormats, value); } public CancellationTokenSource? Cts { get; set; } public bool Started { get; set; } public string Status { get => _status; set => SetField(ref _status, value); } public int Progress { get => _progress; set => SetField(ref _progress, value); } // #9 직링크 길이 미상 시 진행률 바를 부정확(애니메이션) 모드로 public bool IsIndeterminate { get => _isIndeterminate; set => SetField(ref _isIndeterminate, value); } public string Segments { get => _segments; set => SetField(ref _segments, value); } public string? OutputPath { get => _outputPath; set => SetField(ref _outputPath, value); } public string? Error { get => _error; set => SetField(ref _error, value); } public DownloadItemViewModel(string title) { _title = title; } public event PropertyChangedEventHandler? PropertyChanged; private void SetField(ref T field, T value, [CallerMemberName] string? name = null) { if (Equals(field, value)) return; field = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } }