From 29aac7ed8f92af11adb056b4faea8cfc5508dd27 Mon Sep 17 00:00:00 2001 From: Elwador <75888166+Elwador@users.noreply.github.com> Date: Mon, 24 Jun 2024 17:40:20 +0200 Subject: [PATCH] Add - Added option to define the Metadata Title Add - Added option to include the description in the Metadata Add - Added option to include subtitles that only translate signs Fix - en-Us Calendar language --- CRD/Downloader/CRAuth.cs | 2 + CRD/Downloader/CrEpisode.cs | 1 + CRD/Downloader/CrSeries.cs | 1 + CRD/Downloader/Crunchyroll.cs | 74 +++++++++++++-- CRD/Utils/Files/FileNameManager.cs | 2 +- CRD/Utils/Http/HttpClientReq.cs | 6 ++ CRD/Utils/Muxing/Merger.cs | 22 ++++- CRD/Utils/Structs/CrDownloadOptions.cs | 10 +- CRD/Utils/Structs/EpisodeStructs.cs | 1 + CRD/Utils/Structs/Playback.cs | 2 +- CRD/Utils/Structs/Structs.cs | 2 + CRD/ViewModels/DownloadsPageViewModel.cs | 2 +- CRD/ViewModels/SettingsPageViewModel.cs | 114 +++++------------------ CRD/Views/SettingsPageView.axaml | 20 ++++ 14 files changed, 152 insertions(+), 107 deletions(-) diff --git a/CRD/Downloader/CRAuth.cs b/CRD/Downloader/CRAuth.cs index ecbee79..e111eef 100644 --- a/CRD/Downloader/CRAuth.cs +++ b/CRD/Downloader/CRAuth.cs @@ -167,6 +167,8 @@ public class CrAuth{ } if (crunInstance.Token?.refresh_token != null){ + HttpClientReq.Instance.SetETPCookie(crunInstance.Token.refresh_token); + await GetProfile(); } diff --git a/CRD/Downloader/CrEpisode.cs b/CRD/Downloader/CrEpisode.cs index 694a4ca..0e2f46e 100644 --- a/CRD/Downloader/CrEpisode.cs +++ b/CRD/Downloader/CrEpisode.cs @@ -198,6 +198,7 @@ public class CrEpisode(){ DownloadSpeed = 0 }; epMeta.AvailableSubs = item.SubtitleLocales; + epMeta.Description = item.Description; if (episodeP.EpisodeAndLanguages.Langs.Count > 0){ epMeta.SelectedDubs = dubLang .Where(language => episodeP.EpisodeAndLanguages.Langs.Any(epLang => epLang.CrLocale == language)) diff --git a/CRD/Downloader/CrSeries.cs b/CRD/Downloader/CrSeries.cs index 255e3ef..7b74313 100644 --- a/CRD/Downloader/CrSeries.cs +++ b/CRD/Downloader/CrSeries.cs @@ -94,6 +94,7 @@ public class CrSeries(){ Time = 0, DownloadSpeed = 0 }; + epMeta.Description = item.Description; epMeta.AvailableSubs = item.SubtitleLocales; if (episode.Langs.Count > 0){ epMeta.SelectedDubs = dubLang diff --git a/CRD/Downloader/Crunchyroll.cs b/CRD/Downloader/Crunchyroll.cs index 2cb0122..cfb150b 100644 --- a/CRD/Downloader/Crunchyroll.cs +++ b/CRD/Downloader/Crunchyroll.cs @@ -11,10 +11,12 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Web; +using System.Xml; using Avalonia.Media; using CRD.Utils; using CRD.Utils.CustomList; using CRD.Utils.DRM; +using CRD.Utils.Files; using CRD.Utils.HLS; using CRD.Utils.Muxing; using CRD.Utils.Sonarr; @@ -148,7 +150,7 @@ public class Crunchyroll{ CrunOptions.SimultaneousDownloads = 2; CrunOptions.AccentColor = Colors.SlateBlue.ToString(); CrunOptions.Theme = "System"; - CrunOptions.SelectedCalendarLanguage = "de"; + CrunOptions.SelectedCalendarLanguage = "default"; CrunOptions.DlVideoOnce = true; CrunOptions.StreamEndpoint = "web/firefox"; CrunOptions.SubsAddScaledBorder = ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes; @@ -371,7 +373,7 @@ public class Crunchyroll{ } - public async Task DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options, bool? isSeries){ + public async Task DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options){ ActiveDownloads++; data.DownloadProgress = new DownloadProgress(){ @@ -416,7 +418,7 @@ public class Crunchyroll{ SkipSubMux = options.SkipSubsMux, Output = res.FileName, Mp4 = options.Mp4, - VideoTitle = options.VideoTitle, + VideoTitle = res.VideoTitle, Novids = options.Novids, NoCleanup = options.Nocleanup, DefaultAudio = Languages.FindLang(options.DefaultAudio), @@ -425,7 +427,8 @@ public class Crunchyroll{ ForceMuxer = options.Force, SyncTiming = options.SyncTiming, CcTag = options.CcTag, - KeepAllVideos = true + KeepAllVideos = true, + MuxDescription = options.IncludeVideoDescription }, res.FileName); @@ -488,6 +491,15 @@ public class Crunchyroll{ filename = newFilePath; } + bool muxDesc = false; + if (options.MuxDescription){ + if (File.Exists($"{filename}.xml")){ + muxDesc = true; + } else{ + Console.Error.WriteLine("No xml description file found to mux description"); + } + } + var merger = new Merger(new MergerOptions{ OnlyVid = data.Where(a => a.Type == DownloadMediaType.Video).Select(a => new MergerInput{ Language = a.Lang, Path = a.Path ?? string.Empty }).ToList(), @@ -508,7 +520,8 @@ public class Crunchyroll{ Sub = options.DefaultSub }, CcTag = options.CcTag, - mp3 = muxToMp3 + mp3 = muxToMp3, + MuxDescription = muxDesc }); if (!File.Exists(CfgManager.PathFFMPEG)){ @@ -1336,11 +1349,42 @@ public class Crunchyroll{ // variables.Add(new Variable("height", quality == 0 ? plQuality.Last().RESOLUTION.Height : plQuality[quality - 1].RESOLUTION.Height, false)); // variables.Add(new Variable("width", quality == 0 ? plQuality.Last().RESOLUTION.Width : plQuality[quality - 1].RESOLUTION.Width, false)); + if (options.IncludeVideoDescription){ + string fullPath = (Path.IsPathRooted(fileName) ? fileName : Path.Combine(fileDir, fileName)) + ".xml"; + + if (!File.Exists(fullPath)){ + using (XmlWriter writer = XmlWriter.Create(fullPath)){ + writer.WriteStartDocument(); + writer.WriteStartElement("Tags"); + + writer.WriteStartElement("Tag"); + + writer.WriteStartElement("Targets"); + writer.WriteElementString("TargetTypeValue", "50"); + writer.WriteEndElement(); // End Targets + + writer.WriteStartElement("Simple"); + writer.WriteElementString("Name", "DESCRIPTION"); + writer.WriteElementString("String", data.Description); + writer.WriteEndElement(); // End Simple + + writer.WriteEndElement(); // End Tag + + writer.WriteEndElement(); // End Tags + writer.WriteEndDocument(); + } + } + + Console.WriteLine($"{fileName} has been created with the description."); + } + + return new DownloadResponse{ Data = files, Error = dlFailed, FileName = fileName.Length > 0 ? (Path.IsPathRooted(fileName) ? fileName : Path.Combine(fileDir, fileName)) : "./unknown", - ErrorText = "" + ErrorText = "", + VideoTitle = FileNameManager.ParseFileName(options.VideoTitle, variables, options.Numbers, options.Override).Last() }; } @@ -1381,7 +1425,7 @@ public class Crunchyroll{ sxData.Language = langItem; var isSigns = langItem.Code == audDub && !subsItem.isCC; var isCc = subsItem.isCC; - + sxData.File = Languages.SubsFile(fileName, index + "", langItem, isCc, options.CcTag, isSigns, subsItem.format, !(options.DlSubs.Count == 1 && !options.DlSubs.Contains("all"))); sxData.Path = Path.Combine(fileDir, sxData.File); @@ -1391,7 +1435,7 @@ public class Crunchyroll{ if (files.Any(a => a.Type == DownloadMediaType.Subtitle && (a.Language.CrLocale == langItem.CrLocale || a.Language.Locale == langItem.Locale) && a.Cc == isCc && - a.Signs == isSigns)){ + a.Signs == isSigns) || (!options.IncludeSignsSubs && isSigns)){ continue; } @@ -1404,7 +1448,7 @@ public class Crunchyroll{ if (subsItem.format == "ass"){ subsAssReqResponse.ResponseContent = '\ufeff' + subsAssReqResponse.ResponseContent; var sBodySplit = subsAssReqResponse.ResponseContent.Split(new[]{ "\r\n" }, StringSplitOptions.None).ToList(); - // Insert 'ScaledBorderAndShadow: yes' after the second line + // Insert 'ScaledBorderAndShadow' after the second line if (sBodySplit.Count > 2){ if (options.SubsAddScaledBorder == ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes){ sBodySplit.Insert(2, "ScaledBorderAndShadow: yes"); @@ -1424,6 +1468,8 @@ public class Crunchyroll{ var keysList = FontsManager.ExtractFontsFromAss(subsAssReqResponse.ResponseContent); sxData.Fonts = FontsManager.Instance.GetDictFromKeyList(keysList); } + } else if (subsItem.format == "vtt"){ + // TODO } File.WriteAllText(sxData.Path, subsAssReqResponse.ResponseContent); @@ -1591,6 +1637,11 @@ public class Crunchyroll{ } temppbData.Meta = new PlaybackMeta(){ AudioLocale = playStream.AudioLocale, Versions = playStream.Versions, Bifs = new List{ playStream.Bifs }, MediaId = mediaId }; + + if (playStream.Captions != null){ + temppbData.Meta.Captions = playStream.Captions; + } + temppbData.Meta.Subtitles = new Subtitles(); foreach (var playStreamSubtitle in playStream.Subtitles){ Subtitle sub = playStreamSubtitle.Value; @@ -1646,6 +1697,11 @@ public class Crunchyroll{ } temppbData.Meta = new PlaybackMeta(){ AudioLocale = playStream.AudioLocale, Versions = playStream.Versions, Bifs = new List{ playStream.Bifs }, MediaId = mediaId }; + + if (playStream.Captions != null){ + temppbData.Meta.Captions = playStream.Captions; + } + temppbData.Meta.Subtitles = new Subtitles(); foreach (var playStreamSubtitle in playStream.Subtitles){ Subtitle sub = playStreamSubtitle.Value; diff --git a/CRD/Utils/Files/FileNameManager.cs b/CRD/Utils/Files/FileNameManager.cs index afe76bc..44e5fa3 100644 --- a/CRD/Utils/Files/FileNameManager.cs +++ b/CRD/Utils/Files/FileNameManager.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text.RegularExpressions; using CRD.Utils.Structs; -namespace CRD.Utils; +namespace CRD.Utils.Files; public class FileNameManager{ public static List ParseFileName(string input, List variables, int numbers, List @override){ diff --git a/CRD/Utils/Http/HttpClientReq.cs b/CRD/Utils/Http/HttpClientReq.cs index 674dfe1..f4af4e3 100644 --- a/CRD/Utils/Http/HttpClientReq.cs +++ b/CRD/Utils/Http/HttpClientReq.cs @@ -54,8 +54,14 @@ public class HttpClientReq{ Domain = "crunchyroll.com", Path = "/", }; + + var cookie2 = new Cookie("c_locale", "en-US"){ + Domain = "crunchyroll.com", + Path = "/", + }; handler.CookieContainer.Add(cookie); + handler.CookieContainer.Add(cookie2); } public async Task<(bool IsOk, string ResponseContent)> SendHttpRequest(HttpRequestMessage request){ diff --git a/CRD/Utils/Muxing/Merger.cs b/CRD/Utils/Muxing/Merger.cs index 1c370ea..35e14f2 100644 --- a/CRD/Utils/Muxing/Merger.cs +++ b/CRD/Utils/Muxing/Merger.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using CRD.Utils.Structs; +using DynamicData; namespace CRD.Utils.Muxing; @@ -36,7 +37,7 @@ public class Merger{ if (!hasVideo || options.KeepAllVideos == true){ args.Add($"-i \"{vid.Path}\""); metaData.Add($"-map {index}:v"); - metaData.Add($"-metadata:s:v:{index} title=\"{(options.VideoTitle ?? vid.Language.Name)}\""); + metaData.Add($"-metadata:s:v:{index} title=\"{(vid.Language.Name)}\""); hasVideo = true; index++; } @@ -129,7 +130,7 @@ public class Merger{ args.Add("--video-tracks 0"); args.Add("--no-audio"); - string trackName = $"{(options.VideoTitle ?? vid.Language.Name)}"; + string trackName = $"{(vid.Language.Name)}"; args.Add($"--track-name 0:\"{trackName}\""); args.Add($"--language 0:{vid.Language.Code}"); @@ -194,6 +195,16 @@ public class Merger{ args.Add($"--chapters \"{options.Chapters[0].Path}\""); } + if (!string.IsNullOrEmpty(options.VideoTitle)){ + args.Add($"--title \"{options.VideoTitle}\""); + } + + if (options.MuxDescription){ + args.Add($"--global-tags \"{Path.Combine(Path.GetDirectoryName(options.Output), Path.GetFileNameWithoutExtension(options.Output))}.xml\""); + } + + + return string.Join(" ", args); } @@ -230,6 +241,10 @@ public class Merger{ .ToList(); allMediaFiles.ForEach(file => DeleteFile(file.Path)); allMediaFiles.ForEach(file => DeleteFile(file.Path + ".resume")); + + if (options.MuxDescription){ + DeleteFile(Path.Combine(Path.GetDirectoryName(options.Output), Path.GetFileNameWithoutExtension(options.Output)) + ".xml"); + } // Delete chapter files if any options.Chapters?.ForEach(chapter => DeleteFile(chapter.Path)); @@ -278,6 +293,7 @@ public class CrunchyMuxOptions{ public bool? KeepAllVideos{ get; set; } public bool? Novids{ get; set; } public bool Mp4{ get; set; } + public bool MuxDescription{ get; set; } public string ForceMuxer{ get; set; } public bool? NoCleanup{ get; set; } public string VideoTitle{ get; set; } @@ -302,8 +318,8 @@ public class MergerOptions{ public bool? SkipSubMux{ get; set; } public MuxOptions Options{ get; set; } public Defaults Defaults{ get; set; } - public bool mp3{ get; set; } + public bool MuxDescription{ get; set; } } public class MuxOptions{ diff --git a/CRD/Utils/Structs/CrDownloadOptions.cs b/CRD/Utils/Structs/CrDownloadOptions.cs index 54e7bba..9e1be50 100644 --- a/CRD/Utils/Structs/CrDownloadOptions.cs +++ b/CRD/Utils/Structs/CrDownloadOptions.cs @@ -56,14 +56,20 @@ public class CrDownloadOptions{ [YamlMember(Alias = "subs_add_scaled_border", ApplyNamingConventions = false)] public ScaledBorderAndShadowSelection SubsAddScaledBorder{ get; set; } + [YamlMember(Alias = "include_signs_subs", ApplyNamingConventions = false)] + public bool IncludeSignsSubs{ get; set; } + [YamlMember(Alias = "mux_mp4", ApplyNamingConventions = false)] public bool Mp4{ get; set; } [YamlIgnore] public List Override{ get; set; } - [YamlIgnore] - public string VideoTitle{ get; set; } + [YamlMember(Alias = "mux_video_title", ApplyNamingConventions = false)] + public string? VideoTitle{ get; set; } + + [YamlMember(Alias = "mux_video_description", ApplyNamingConventions = false)] + public bool IncludeVideoDescription{ get; set; } [YamlIgnore] public string Force{ get; set; } diff --git a/CRD/Utils/Structs/EpisodeStructs.cs b/CRD/Utils/Structs/EpisodeStructs.cs index 3dc7686..e74ac7c 100644 --- a/CRD/Utils/Structs/EpisodeStructs.cs +++ b/CRD/Utils/Structs/EpisodeStructs.cs @@ -236,6 +236,7 @@ public class CrunchyEpMeta{ public string? SeasonTitle{ get; set; } public string? EpisodeNumber{ get; set; } public string? EpisodeTitle{ get; set; } + public string? Description{ get; set; } public string? SeasonId{ get; set; } public string? Season{ get; set; } public string? ShowId{ get; set; } diff --git a/CRD/Utils/Structs/Playback.cs b/CRD/Utils/Structs/Playback.cs index dd74263..2944b34 100644 --- a/CRD/Utils/Structs/Playback.cs +++ b/CRD/Utils/Structs/Playback.cs @@ -24,7 +24,7 @@ public class PlaybackMeta{ public List? Versions{ get; set; } [JsonProperty("audio_locale")] public Locale? AudioLocale{ get; set; } [JsonProperty("closed_captions")] public Subtitles? ClosedCaptions{ get; set; } - public Dictionary? Captions{ get; set; } + public Dictionary? Captions{ get; set; } } public class SubtitleInfo{ diff --git a/CRD/Utils/Structs/Structs.cs b/CRD/Utils/Structs/Structs.cs index bd957a7..d9952ca 100644 --- a/CRD/Utils/Structs/Structs.cs +++ b/CRD/Utils/Structs/Structs.cs @@ -62,6 +62,8 @@ public struct Episode{ public struct DownloadResponse{ public List Data{ get; set; } public string FileName{ get; set; } + + public string VideoTitle{ get; set; } public bool Error{ get; set; } public string ErrorText{ get; set; } } diff --git a/CRD/ViewModels/DownloadsPageViewModel.cs b/CRD/ViewModels/DownloadsPageViewModel.cs index a7d1cb9..87d9803 100644 --- a/CRD/ViewModels/DownloadsPageViewModel.cs +++ b/CRD/ViewModels/DownloadsPageViewModel.cs @@ -227,7 +227,7 @@ public partial class DownloadItemModel : INotifyPropertyChanged{ epMeta.DownloadProgress.IsDownloading = true; Paused = !epMeta.Paused && !isDownloading || epMeta.Paused; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Paused))); - await Crunchyroll.Instance.DownloadEpisode(epMeta, Crunchyroll.Instance.CrunOptions, false); + await Crunchyroll.Instance.DownloadEpisode(epMeta, Crunchyroll.Instance.CrunOptions); } } diff --git a/CRD/ViewModels/SettingsPageViewModel.cs b/CRD/ViewModels/SettingsPageViewModel.cs index 3889a7f..e40b165 100644 --- a/CRD/ViewModels/SettingsPageViewModel.cs +++ b/CRD/ViewModels/SettingsPageViewModel.cs @@ -38,6 +38,9 @@ public partial class SettingsPageViewModel : ViewModelBase{ [ObservableProperty] private bool _addScaledBorderAndShadow = false; + [ObservableProperty] + private bool _includeSignSubs = false; + [ObservableProperty] private ComboBoxItem _selectedScaledBorderAndShadow; @@ -48,6 +51,9 @@ public partial class SettingsPageViewModel : ViewModelBase{ [ObservableProperty] private bool _muxToMp4; + + [ObservableProperty] + private bool _includeEpisodeDescription; [ObservableProperty] private bool _downloadVideoForEveryDub; @@ -66,6 +72,9 @@ public partial class SettingsPageViewModel : ViewModelBase{ [ObservableProperty] private string _fileName = ""; + + [ObservableProperty] + private string _fileTitle = ""; [ObservableProperty] private ObservableCollection _mkvMergeOptions = new(); @@ -319,6 +328,9 @@ public partial class SettingsPageViewModel : ViewModelBase{ AddScaledBorderAndShadow = options.SubsAddScaledBorder is ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo or ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes; SelectedScaledBorderAndShadow = GetScaledBorderAndShadowFromOptions(options); + IncludeEpisodeDescription = options.IncludeVideoDescription; + FileTitle = options.VideoTitle ?? ""; + IncludeSignSubs = options.IncludeSignsSubs; DownloadVideo = !options.Novids; DownloadAudio = !options.Noaudio; DownloadVideoForEveryDub = !options.DlVideoOnce; @@ -375,6 +387,8 @@ public partial class SettingsPageViewModel : ViewModelBase{ UpdateSubAndDubString(); + Crunchyroll.Instance.CrunOptions.IncludeVideoDescription = IncludeEpisodeDescription; + Crunchyroll.Instance.CrunOptions.VideoTitle = FileTitle; Crunchyroll.Instance.CrunOptions.Novids = !DownloadVideo; Crunchyroll.Instance.CrunOptions.Noaudio = !DownloadAudio; Crunchyroll.Instance.CrunOptions.DlVideoOnce = !DownloadVideoForEveryDub; @@ -383,6 +397,7 @@ public partial class SettingsPageViewModel : ViewModelBase{ Crunchyroll.Instance.CrunOptions.SkipSubsMux = SkipSubMux; Crunchyroll.Instance.CrunOptions.Numbers = LeadingNumbers; Crunchyroll.Instance.CrunOptions.FileName = FileName; + Crunchyroll.Instance.CrunOptions.IncludeSignsSubs = IncludeSignSubs; Crunchyroll.Instance.CrunOptions.SubsAddScaledBorder = GetScaledBorderAndShadowSelection(); @@ -611,71 +626,17 @@ public partial class SettingsPageViewModel : ViewModelBase{ private void Changes(object? sender, NotifyCollectionChangedEventArgs e){ UpdateSettings(); } + + protected override void OnPropertyChanged(PropertyChangedEventArgs e){ + base.OnPropertyChanged(e); - partial void OnDownloadAudioChanged(bool value){ + if (e.PropertyName is nameof(SelectedSubs) or nameof(SelectedDubs) or nameof(CustomAccentColor) or nameof(ListBoxColor) or nameof(CurrentAppTheme) or nameof(UseCustomAccent) or nameof(LogMode)){ + return; + } + UpdateSettings(); } - - partial void OnDownloadChaptersChanged(bool value){ - UpdateSettings(); - } - - partial void OnDownloadVideoChanged(bool value){ - UpdateSettings(); - } - - partial void OnFileNameChanged(string value){ - UpdateSettings(); - } - - partial void OnLeadingNumbersChanged(int value){ - UpdateSettings(); - } - - partial void OnMuxToMp4Changed(bool value){ - UpdateSettings(); - } - - partial void OnSelectedHSLangChanged(ComboBoxItem value){ - UpdateSettings(); - } - - partial void OnSimultaneousDownloadsChanged(int value){ - UpdateSettings(); - } - - partial void OnSelectedAudioQualityChanged(ComboBoxItem? value){ - UpdateSettings(); - } - - partial void OnSelectedVideoQualityChanged(ComboBoxItem? value){ - UpdateSettings(); - } - - partial void OnHistoryChanged(bool value){ - UpdateSettings(); - } - - partial void OnSonarrHostChanged(string value){ - UpdateSettings(); - } - - partial void OnSonarrPortChanged(string value){ - UpdateSettings(); - } - - partial void OnSonarrApiKeyChanged(string value){ - UpdateSettings(); - } - - partial void OnSonarrUseSslChanged(bool value){ - UpdateSettings(); - } - - partial void OnSonarrUseSonarrNumberingChanged(bool value){ - UpdateSettings(); - } - + partial void OnLogModeChanged(bool value){ UpdateSettings(); if (value){ @@ -684,34 +645,7 @@ public partial class SettingsPageViewModel : ViewModelBase{ CfgManager.DisableLogMode(); } } - - partial void OnSelectedDefaultDubLangChanged(ComboBoxItem value){ - UpdateSettings(); - } - - partial void OnSelectedDefaultSubLangChanged(ComboBoxItem value){ - UpdateSettings(); - } - - partial void OnSkipSubMuxChanged(bool value){ - UpdateSettings(); - } - - partial void OnDownloadVideoForEveryDubChanged(bool value){ - UpdateSettings(); - } - - partial void OnSelectedStreamEndpointChanged(ComboBoxItem value){ - UpdateSettings(); - } - - partial void OnAddScaledBorderAndShadowChanged(bool value){ - UpdateSettings(); - } - - partial void OnSelectedScaledBorderAndShadowChanged(ComboBoxItem value){ - UpdateSettings(); - } + } public class MuxingParam{ diff --git a/CRD/Views/SettingsPageView.axaml b/CRD/Views/SettingsPageView.axaml index bdbb909..3a5fb54 100644 --- a/CRD/Views/SettingsPageView.axaml +++ b/CRD/Views/SettingsPageView.axaml @@ -119,6 +119,12 @@ + + + + + + @@ -283,6 +289,20 @@ + + + + + + + + + + + +