using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.FileName; using DownKyi.Core.Settings; using DownKyi.Core.Settings.Models; using DownKyi.Events; using DownKyi.Models; using DownKyi.Utils; using Prism.Commands; using Prism.Events; using Prism.Regions; namespace DownKyi.ViewModels.Settings; public class ViewVideoViewModel : ViewModelBase { public const string Tag = "PageSettingsVideo"; private bool isOnNavigatedTo; #region 页面属性申明 private List videoCodecs; public List VideoCodecs { get => videoCodecs; set => SetProperty(ref videoCodecs, value); } private Quality selectedVideoCodec; public Quality SelectedVideoCodec { get => selectedVideoCodec; set => SetProperty(ref selectedVideoCodec, value); } private List videoQualityList; public List VideoQualityList { get => videoQualityList; set => SetProperty(ref videoQualityList, value); } private Quality _selectedVideoQuality; public Quality SelectedVideoQuality { get => _selectedVideoQuality; set => SetProperty(ref _selectedVideoQuality, value); } private List _audioQualityList; public List AudioQualityList { get => _audioQualityList; set => SetProperty(ref _audioQualityList, value); } private Quality _selectedAudioQuality; public Quality SelectedAudioQuality { get => _selectedAudioQuality; set => SetProperty(ref _selectedAudioQuality, value); } private List _videoParseTypeList; public List VideoParseTypeList { get => _videoParseTypeList; set => SetProperty(ref _videoParseTypeList, value); } private VideoParseType _selectedVideoParseType; public VideoParseType SelectedVideoParseType { get => _selectedVideoParseType; set => SetProperty(ref _selectedVideoParseType, value); } private bool _isTranscodingFlvToMp4; public bool IsTranscodingFlvToMp4 { get => _isTranscodingFlvToMp4; set => SetProperty(ref _isTranscodingFlvToMp4, value); } private bool _isTranscodingAacToMp3; public bool IsTranscodingAacToMp3 { get => _isTranscodingAacToMp3; set => SetProperty(ref _isTranscodingAacToMp3, value); } private bool _isUseDefaultDirectory; public bool IsUseDefaultDirectory { get => _isUseDefaultDirectory; set => SetProperty(ref _isUseDefaultDirectory, value); } private string _saveVideoDirectory; public string SaveVideoDirectory { get => _saveVideoDirectory; set => SetProperty(ref _saveVideoDirectory, value); } private bool _downloadAll; public bool DownloadAll { get => _downloadAll; set => SetProperty(ref _downloadAll, value); } private bool _downloadAudio; public bool DownloadAudio { get => _downloadAudio; set => SetProperty(ref _downloadAudio, value); } private bool _downloadVideo; public bool DownloadVideo { get => _downloadVideo; set => SetProperty(ref _downloadVideo, value); } private bool _downloadDanmaku; public bool DownloadDanmaku { get => _downloadDanmaku; set => SetProperty(ref _downloadDanmaku, value); } private bool _downloadSubtitle; public bool DownloadSubtitle { get => _downloadSubtitle; set => SetProperty(ref _downloadSubtitle, value); } private bool _downloadCover; public bool DownloadCover { get => _downloadCover; set => SetProperty(ref _downloadCover, value); } private ObservableCollection _selectedFileName; public ObservableCollection SelectedFileName { get => _selectedFileName; set => SetProperty(ref _selectedFileName, value); } private ObservableCollection _optionalFields; public ObservableCollection OptionalFields { get => _optionalFields; set => SetProperty(ref _optionalFields, value); } private int _selectedOptionalField; public int SelectedOptionalField { get => _selectedOptionalField; set => SetProperty(ref _selectedOptionalField, value); } private List _fileNamePartTimeFormatList; public List FileNamePartTimeFormatList { get => _fileNamePartTimeFormatList; set => SetProperty(ref _fileNamePartTimeFormatList, value); } private string _selectedFileNamePartTimeFormat; public string SelectedFileNamePartTimeFormat { get => _selectedFileNamePartTimeFormat; set => SetProperty(ref _selectedFileNamePartTimeFormat, value); } private List _orderFormatList; public List OrderFormatList { get => _orderFormatList; set => SetProperty(ref _orderFormatList, value); } private OrderFormatDisplay _orderFormatDisplay; public OrderFormatDisplay OrderFormatDisplay { get => _orderFormatDisplay; set => SetProperty(ref _orderFormatDisplay, value); } #endregion public ViewVideoViewModel(IEventAggregator eventAggregator) : base(eventAggregator) { #region 属性初始化 // 优先下载的视频编码 VideoCodecs = Constant.GetCodecIds(); //VideoCodecs = new List //{ // "H.264/AVC", // "H.265/HEVC", //}; // 优先下载画质 VideoQualityList = Constant.GetResolutions(); // 优先下载音质 AudioQualityList = Constant.GetAudioQualities(); //AudioQualityList.RemoveAt(3); AudioQualityList[3].Id += 1000; AudioQualityList[4].Id += 1000; // 首选视频解析方式 VideoParseTypeList = new List { new() { Name = "API(解析快、易风控)", Id = 0 }, new() { Name = "WebPage(解析慢、不易风控)", Id = 1 }, }; // 文件命名格式 SelectedFileName = new ObservableCollection(); SelectedFileName.CollectionChanged += (sender, e) => { // 当前显示的命名格式part var fileName = SelectedFileName.Select(item => item.Id).ToList(); var isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName); PublishTip(isSucceed); }; OptionalFields = new ObservableCollection(); foreach (FileNamePart item in Enum.GetValues(typeof(FileNamePart))) { var display = DisplayFileNamePart(item); OptionalFields.Add(new DisplayFileNamePart { Id = item, Title = display }); } SelectedOptionalField = -1; // 文件命名中的时间格式 FileNamePartTimeFormatList = new List { "yyyy-MM-dd", "yyyy.MM.dd", }; // 文件命名中的序号格式 OrderFormatList = new List { new() { Name = DictionaryResource.GetString("OrderFormatNatural"), OrderFormat = OrderFormat.NATURAL }, new() { Name = DictionaryResource.GetString("OrderFormatLeadingZeros"), OrderFormat = OrderFormat.LEADING_ZEROS }, }; #endregion } /// /// 导航到页面时执行 /// /// public override void OnNavigatedTo(NavigationContext navigationContext) { base.OnNavigatedTo(navigationContext); isOnNavigatedTo = true; // 优先下载的视频编码 var videoCodecs = SettingsManager.GetInstance().GetVideoCodecs(); //SelectedVideoCodec = GetVideoCodecsString(videoCodecs); SelectedVideoCodec = VideoCodecs.FirstOrDefault(t => { return t.Id == videoCodecs; }); // 优先下载画质 var quality = SettingsManager.GetInstance().GetQuality(); SelectedVideoQuality = VideoQualityList.FirstOrDefault(t => t.Id == quality); // 优先下载音质 var audioQuality = SettingsManager.GetInstance().GetAudioQuality(); SelectedAudioQuality = AudioQualityList.FirstOrDefault(t => t.Id == audioQuality); // 首选视频解析方式 var videoParseType = SettingsManager.GetInstance().GetVideoParseType(); SelectedVideoParseType = VideoParseTypeList.FirstOrDefault(t => t.Id == videoParseType); // 是否下载flv视频后转码为mp4 var isTranscodingFlvToMp4 = SettingsManager.GetInstance().IsTranscodingFlvToMp4(); IsTranscodingFlvToMp4 = isTranscodingFlvToMp4 == AllowStatus.YES; // 是否下载aac音频后转码为mp3 var isTranscodingAacToMp3 = SettingsManager.GetInstance().IsTranscodingAacToMp3(); IsTranscodingAacToMp3 = isTranscodingAacToMp3 == AllowStatus.YES; // 是否使用默认下载目录 var isUseSaveVideoRootPath = SettingsManager.GetInstance().IsUseSaveVideoRootPath(); IsUseDefaultDirectory = isUseSaveVideoRootPath == AllowStatus.YES; // 默认下载目录 SaveVideoDirectory = SettingsManager.GetInstance().GetSaveVideoRootPath(); // 下载内容 var videoContent = SettingsManager.GetInstance().GetVideoContent(); DownloadAudio = videoContent.DownloadAudio; DownloadVideo = videoContent.DownloadVideo; DownloadDanmaku = videoContent.DownloadDanmaku; DownloadSubtitle = videoContent.DownloadSubtitle; DownloadCover = videoContent.DownloadCover; if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } else { DownloadAll = false; } // 文件命名格式 var fileNameParts = SettingsManager.GetInstance().GetFileNameParts(); SelectedFileName.Clear(); foreach (var item in fileNameParts) { var display = DisplayFileNamePart(item); SelectedFileName.Add(new DisplayFileNamePart { Id = item, Title = display }); } // 文件命名中的时间格式 SelectedFileNamePartTimeFormat = SettingsManager.GetInstance().GetFileNamePartTimeFormat(); // 文件命名中的序号格式 OrderFormat orderFormat = SettingsManager.GetInstance().GetOrderFormat(); OrderFormatDisplay = OrderFormatList.FirstOrDefault(t => { return t.OrderFormat == orderFormat; }); isOnNavigatedTo = false; } #region 命令申明 // 优先下载的视频编码事件 private DelegateCommand? _videoCodecsCommand; public DelegateCommand VideoCodecsCommand => _videoCodecsCommand ??= new DelegateCommand(ExecuteVideoCodecsCommand); /// /// 优先下载的视频编码事件 /// /// private void ExecuteVideoCodecsCommand(object parameter) { //VideoCodecs videoCodecs = GetVideoCodecs(parameter); if (parameter is not Quality videoCodecs) { return; } var isSucceed = SettingsManager.GetInstance().SetVideoCodecs(videoCodecs.Id); PublishTip(isSucceed); } // 优先下载画质事件 private DelegateCommand? _videoQualityCommand; public DelegateCommand VideoQualityCommand => _videoQualityCommand ??= new DelegateCommand(ExecuteVideoQualityCommand); /// /// 优先下载画质事件 /// /// private void ExecuteVideoQualityCommand(object parameter) { if (!(parameter is Quality resolution)) { return; } bool isSucceed = SettingsManager.GetInstance().SetQuality(resolution.Id); PublishTip(isSucceed); } // 优先下载音质事件 private DelegateCommand? _audioQualityCommand; public DelegateCommand AudioQualityCommand => _audioQualityCommand ??= new DelegateCommand(ExecuteAudioQualityCommand); /// /// 优先下载音质事件 /// /// private void ExecuteAudioQualityCommand(object parameter) { if (!(parameter is Quality quality)) { return; } bool isSucceed = SettingsManager.GetInstance().SetAudioQuality(quality.Id); PublishTip(isSucceed); } // 首选视频解析线路事件 private DelegateCommand? _videoParseTypeCommand; public DelegateCommand VideoParseTypeCommand => _videoParseTypeCommand ??= new DelegateCommand(ExecuteVideoParseTypeCommand); /// /// 首选视频解析线路事件 /// /// private void ExecuteVideoParseTypeCommand(object parameter) { if (parameter is not VideoParseType type) { return; } var isSucceed = SettingsManager.GetInstance().SetVideoParseType(type.Id ?? 1); PublishTip(isSucceed); } // 是否下载flv视频后转码为mp4事件 private DelegateCommand? _isTranscodingFlvToMp4Command; public DelegateCommand IsTranscodingFlvToMp4Command => _isTranscodingFlvToMp4Command ??= new DelegateCommand(ExecuteIsTranscodingFlvToMp4Command); /// /// 是否下载flv视频后转码为mp4事件 /// private void ExecuteIsTranscodingFlvToMp4Command() { var isTranscodingFlvToMp4 = IsTranscodingFlvToMp4 ? AllowStatus.YES : AllowStatus.NO; var isSucceed = SettingsManager.GetInstance().IsTranscodingFlvToMp4(isTranscodingFlvToMp4); PublishTip(isSucceed); } // 是否下载aac音频后转码为mp3事件 private DelegateCommand? _isTranscodingAacToMp3Command; public DelegateCommand IsTranscodingAacToMp3Command => _isTranscodingAacToMp3Command ??= new DelegateCommand(ExecuteIsTranscodingAacToMp3Command); /// /// 是否下载aac音频后转码为mp3事件 /// private void ExecuteIsTranscodingAacToMp3Command() { var isTranscodingAacToMp3 = IsTranscodingAacToMp3 ? AllowStatus.YES : AllowStatus.NO; var isSucceed = SettingsManager.GetInstance().IsTranscodingAacToMp3(isTranscodingAacToMp3); PublishTip(isSucceed); } // 是否使用默认下载目录事件 private DelegateCommand? _isUseDefaultDirectoryCommand; public DelegateCommand IsUseDefaultDirectoryCommand => _isUseDefaultDirectoryCommand ??= new DelegateCommand(ExecuteIsUseDefaultDirectoryCommand); /// /// 是否使用默认下载目录事件 /// private void ExecuteIsUseDefaultDirectoryCommand() { var isUseDefaultDirectory = IsUseDefaultDirectory ? AllowStatus.YES : AllowStatus.NO; var isSucceed = SettingsManager.GetInstance().IsUseSaveVideoRootPath(isUseDefaultDirectory); PublishTip(isSucceed); } // 修改默认下载目录事件 private DelegateCommand? _changeSaveVideoDirectoryCommand; public DelegateCommand ChangeSaveVideoDirectoryCommand => _changeSaveVideoDirectoryCommand ??= new DelegateCommand(ExecuteChangeSaveVideoDirectoryCommand); /// /// 修改默认下载目录事件 /// private async void ExecuteChangeSaveVideoDirectoryCommand() { var directory = await DialogUtils.SetDownloadDirectory(); if (string.IsNullOrEmpty(directory)) { return; } var isSucceed = SettingsManager.GetInstance().SetSaveVideoRootPath(directory); PublishTip(isSucceed); if (isSucceed) { SaveVideoDirectory = directory; } } // 所有内容选择事件 private DelegateCommand? _downloadAllCommand; public DelegateCommand DownloadAllCommand => _downloadAllCommand ??= new DelegateCommand(ExecuteDownloadAllCommand); /// /// 所有内容选择事件 /// private void ExecuteDownloadAllCommand() { if (DownloadAll) { DownloadAudio = true; DownloadVideo = true; DownloadDanmaku = true; DownloadSubtitle = true; DownloadCover = true; } else { DownloadAudio = false; DownloadVideo = false; DownloadDanmaku = false; DownloadSubtitle = false; DownloadCover = false; } SetVideoContent(); } // 音频选择事件 private DelegateCommand? _downloadAudioCommand; public DelegateCommand DownloadAudioCommand => _downloadAudioCommand ??= new DelegateCommand(ExecuteDownloadAudioCommand); /// /// 音频选择事件 /// private void ExecuteDownloadAudioCommand() { if (!DownloadAudio) { DownloadAll = false; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } SetVideoContent(); } // 视频选择事件 private DelegateCommand? _downloadVideoCommand; public DelegateCommand DownloadVideoCommand => _downloadVideoCommand ??= new DelegateCommand(ExecuteDownloadVideoCommand); /// /// 视频选择事件 /// private void ExecuteDownloadVideoCommand() { if (!DownloadVideo) { DownloadAll = false; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } SetVideoContent(); } // 弹幕选择事件 private DelegateCommand? _downloadDanmakuCommand; public DelegateCommand DownloadDanmakuCommand => _downloadDanmakuCommand ??= new DelegateCommand(ExecuteDownloadDanmakuCommand); /// /// 弹幕选择事件 /// private void ExecuteDownloadDanmakuCommand() { if (!DownloadDanmaku) { DownloadAll = false; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } SetVideoContent(); } // 字幕选择事件 private DelegateCommand? _downloadSubtitleCommand; public DelegateCommand DownloadSubtitleCommand => _downloadSubtitleCommand ??= new DelegateCommand(ExecuteDownloadSubtitleCommand); /// /// 字幕选择事件 /// private void ExecuteDownloadSubtitleCommand() { if (!DownloadSubtitle) { DownloadAll = false; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } SetVideoContent(); } // 封面选择事件 private DelegateCommand? _downloadCoverCommand; public DelegateCommand DownloadCoverCommand => _downloadCoverCommand ??= new DelegateCommand(ExecuteDownloadCoverCommand); /// /// 封面选择事件 /// private void ExecuteDownloadCoverCommand() { if (!DownloadCover) { DownloadAll = false; } if (DownloadAudio && DownloadVideo && DownloadDanmaku && DownloadSubtitle && DownloadCover) { DownloadAll = true; } SetVideoContent(); } // 选中文件名字段右键点击事件 private DelegateCommand? _selectedFileNameRightCommand; public DelegateCommand SelectedFileNameRightCommand => _selectedFileNameRightCommand ??= new DelegateCommand(ExecuteSelectedFileNameRightCommand); /// /// 选中文件名字段右键点击事件 /// /// private void ExecuteSelectedFileNameRightCommand(object parameter) { if (parameter == null) { return; } bool isSucceed = SelectedFileName.Remove((DisplayFileNamePart)parameter); if (!isSucceed) { PublishTip(isSucceed); return; } //List fileName = new List(); //foreach (DisplayFileNamePart item in SelectedFileName) //{ // fileName.Add(item.Id); //} //isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName); //PublishTip(isSucceed); SelectedOptionalField = -1; } // 可选文件名字段点击事件 private DelegateCommand? _optionalFieldsCommand; public DelegateCommand OptionalFieldsCommand => _optionalFieldsCommand ??= new DelegateCommand(ExecuteOptionalFieldsCommand); /// /// 可选文件名字段点击事件 /// /// private void ExecuteOptionalFieldsCommand(object parameter) { if (SelectedOptionalField == -1) { return; } SelectedFileName.Add((DisplayFileNamePart)parameter); var fileName = new List(); foreach (var item in SelectedFileName) { fileName.Add(item.Id); } var isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName); PublishTip(isSucceed); SelectedOptionalField = -1; } // 重置选中文件名字段 private DelegateCommand? _resetCommand; public DelegateCommand ResetCommand => _resetCommand ??= new DelegateCommand(ExecuteResetCommand); /// /// 重置选中文件名字段 /// private void ExecuteResetCommand() { var isSucceed = SettingsManager.GetInstance().SetFileNameParts(null); PublishTip(isSucceed); var fileNameParts = SettingsManager.GetInstance().GetFileNameParts(); SelectedFileName.Clear(); foreach (var item in fileNameParts) { var display = DisplayFileNamePart(item); SelectedFileName.Add(new DisplayFileNamePart { Id = item, Title = display }); } SelectedOptionalField = -1; } // 文件命名中的时间格式事件 private DelegateCommand? _fileNamePartTimeFormatCommand; public DelegateCommand FileNamePartTimeFormatCommand => _fileNamePartTimeFormatCommand ??= new DelegateCommand(ExecuteFileNamePartTimeFormatCommand); /// /// 文件命名中的时间格式事件 /// /// private void ExecuteFileNamePartTimeFormatCommand(object parameter) { if (parameter is not string timeFormat) { return; } var isSucceed = SettingsManager.GetInstance().SetFileNamePartTimeFormat(timeFormat); PublishTip(isSucceed); } // 文件命名中的序号格式事件 private DelegateCommand? _orderFormatCommand; public DelegateCommand OrderFormatCommand => _orderFormatCommand ??= new DelegateCommand(ExecuteOrderFormatCommandCommand); /// /// 文件命名中的序号格式事件 /// /// private void ExecuteOrderFormatCommandCommand(object parameter) { if (parameter is not OrderFormatDisplay orderFormatDisplay) { return; } var isSucceed = SettingsManager.GetInstance().SetOrderFormat(orderFormatDisplay.OrderFormat); PublishTip(isSucceed); } #endregion /// /// 返回VideoCodecs的字符串 /// /// /// //private string GetVideoCodecsString(VideoCodecs videoCodecs) //{ // string codec; // switch (videoCodecs) // { // case Core.Settings.VideoCodecs.NONE: // codec = ""; // break; // case Core.Settings.VideoCodecs.AVC: // codec = "H.264/AVC"; // break; // case Core.Settings.VideoCodecs.HEVC: // codec = "H.265/HEVC"; // break; // default: // codec = ""; // break; // } // return codec; //} /// /// 返回VideoCodecs /// /// /// //private VideoCodecs GetVideoCodecs(string str) //{ // VideoCodecs videoCodecs; // switch (str) // { // case "H.264/AVC": // videoCodecs = Core.Settings.VideoCodecs.AVC; // break; // case "H.265/HEVC": // videoCodecs = Core.Settings.VideoCodecs.HEVC; // break; // default: // videoCodecs = Core.Settings.VideoCodecs.NONE; // break; // } // return videoCodecs; //} /// /// 保存下载视频内容到设置 /// private void SetVideoContent() { var videoContent = new VideoContentSettings { DownloadAudio = DownloadAudio, DownloadVideo = DownloadVideo, DownloadDanmaku = DownloadDanmaku, DownloadSubtitle = DownloadSubtitle, DownloadCover = DownloadCover }; var isSucceed = SettingsManager.GetInstance().SetVideoContent(videoContent); PublishTip(isSucceed); } /// /// 文件名字段显示 /// /// /// private string DisplayFileNamePart(FileNamePart item) { var display = item switch { FileNamePart.ORDER => DictionaryResource.GetString("DisplayOrder"), FileNamePart.SECTION => DictionaryResource.GetString("DisplaySection"), FileNamePart.MAIN_TITLE => DictionaryResource.GetString("DisplayMainTitle"), FileNamePart.PAGE_TITLE => DictionaryResource.GetString("DisplayPageTitle"), FileNamePart.VIDEO_ZONE => DictionaryResource.GetString("DisplayVideoZone"), FileNamePart.AUDIO_QUALITY => DictionaryResource.GetString("DisplayAudioQuality"), FileNamePart.VIDEO_QUALITY => DictionaryResource.GetString("DisplayVideoQuality"), FileNamePart.VIDEO_CODEC => DictionaryResource.GetString("DisplayVideoCodec"), FileNamePart.VIDEO_PUBLISH_TIME => DictionaryResource.GetString("DisplayVideoPublishTime"), FileNamePart.AVID => "avid", FileNamePart.BVID => "bvid", FileNamePart.CID => "cid", FileNamePart.UP_MID => DictionaryResource.GetString("DisplayUpMid"), FileNamePart.UP_NAME => DictionaryResource.GetString("DisplayUpName"), _ => string.Empty }; if ((int)item >= 100) { display = HyphenSeparated.Hyphen[(int)item]; } if (display == " ") { display = DictionaryResource.GetString("DisplaySpace"); } return display; } /// /// 发送需要显示的tip /// /// private void PublishTip(bool isSucceed) { if (isOnNavigatedTo) { return; } if (isSucceed) { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipSettingUpdated")); } else { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipSettingFailed")); } } }