diff --git a/TwitchDownloaderCore/ChatUpdater.cs b/TwitchDownloaderCore/ChatUpdater.cs index 5e1dd01f..faceb073 100644 --- a/TwitchDownloaderCore/ChatUpdater.cs +++ b/TwitchDownloaderCore/ChatUpdater.cs @@ -39,7 +39,8 @@ public async Task UpdateAsync(IProgress progress, CancellationTo int currentStep = 0; int totalSteps = 2; if (_updateOptions.CropBeginning || _updateOptions.CropEnding) totalSteps++; - if (_updateOptions.EmbedMissing || _updateOptions.ReplaceEmbeds) totalSteps++; + if (_updateOptions.OutputFormat is ChatFormat.Json or ChatFormat.Html + && (_updateOptions.EmbedMissing || _updateOptions.ReplaceEmbeds)) totalSteps++; currentStep++; await UpdateVideoInfo(totalSteps, currentStep, progress, cancellationToken); @@ -52,7 +53,8 @@ public async Task UpdateAsync(IProgress progress, CancellationTo } // If we are updating/replacing embeds - if (_updateOptions.EmbedMissing || _updateOptions.ReplaceEmbeds) + if (_updateOptions.OutputFormat is ChatFormat.Json or ChatFormat.Html + && (_updateOptions.EmbedMissing || _updateOptions.ReplaceEmbeds)) { currentStep++; await UpdateEmbeds(currentStep, totalSteps, progress, cancellationToken); diff --git a/TwitchDownloaderCore/ClipDownloader.cs b/TwitchDownloaderCore/ClipDownloader.cs index 403deb49..c7e6fcf5 100644 --- a/TwitchDownloaderCore/ClipDownloader.cs +++ b/TwitchDownloaderCore/ClipDownloader.cs @@ -86,22 +86,23 @@ void DownloadProgressHandler(StreamCopyProgress streamProgress) private async Task GetDownloadUrl() { var listLinks = await TwitchHelper.GetClipLinks(downloadOptions.Id); + var clip = listLinks[0].data.clip; - if (listLinks[0].data.clip.playbackAccessToken is null) + if (clip.playbackAccessToken is null) { throw new NullReferenceException("Invalid Clip, deleted possibly?"); } - if (listLinks[0].data.clip.videoQualities is null || listLinks[0].data.clip.videoQualities.Count == 0) + if (clip.videoQualities is null || clip.videoQualities.Length == 0) { throw new NullReferenceException("Clip has no video qualities, deleted possibly?"); } string downloadUrl = ""; - foreach (var quality in listLinks[0].data.clip.videoQualities) + foreach (var quality in clip.videoQualities) { - if (quality.quality + "p" + (quality.frameRate.ToString() == "30" ? "" : quality.frameRate.ToString()) == downloadOptions.Quality) + if (quality.quality + "p" + (Math.Round(quality.frameRate) == 30 ? "" : Math.Round(quality.frameRate).ToString("F0")) == downloadOptions.Quality) { downloadUrl = quality.sourceURL; } @@ -109,10 +110,10 @@ private async Task GetDownloadUrl() if (downloadUrl == "") { - downloadUrl = listLinks[0].data.clip.videoQualities.First().sourceURL; + downloadUrl = clip.videoQualities.First().sourceURL; } - return downloadUrl + "?sig=" + listLinks[0].data.clip.playbackAccessToken.signature + "&token=" + HttpUtility.UrlEncode(listLinks[0].data.clip.playbackAccessToken.value); + return downloadUrl + "?sig=" + clip.playbackAccessToken.signature + "&token=" + HttpUtility.UrlEncode(clip.playbackAccessToken.value); } private static async Task DownloadFileTaskAsync(string url, string destinationFile, int throttleKib, IProgress progress, CancellationToken cancellationToken) diff --git a/TwitchDownloaderCore/Tools/ClipQualityComparer.cs b/TwitchDownloaderCore/Tools/ClipQualityComparer.cs new file mode 100644 index 00000000..8d8dd876 --- /dev/null +++ b/TwitchDownloaderCore/Tools/ClipQualityComparer.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using TwitchDownloaderCore.TwitchObjects.Gql; + +namespace TwitchDownloaderCore.Tools +{ + public class ClipQualityComparer : IComparer + { + public int Compare(VideoQuality x, VideoQuality y) + { + if (x is null) + { + if (y is null) return 0; + return -1; + } + + if (y is null) return 1; + + if (int.TryParse(x.quality, out var xQuality) | int.TryParse(y.quality, out var yQuality)) + { + if (xQuality < yQuality) return 1; + if (xQuality > yQuality) return -1; + + if (x.frameRate < y.frameRate) return 1; + if (x.frameRate > y.frameRate) return -1; + return 0; + } + + return Math.Clamp(string.Compare(x.quality, y.quality, StringComparison.Ordinal), -1, 1) * -1; + } + } +} \ No newline at end of file diff --git a/TwitchDownloaderCore/Tools/CommentTools.cs b/TwitchDownloaderCore/Tools/CommentTools.cs index cb3d769f..56d8e41f 100644 --- a/TwitchDownloaderCore/Tools/CommentTools.cs +++ b/TwitchDownloaderCore/Tools/CommentTools.cs @@ -15,7 +15,7 @@ public int Compare(Comment x, Comment y) return -1; } - if (y is null) return -1; + if (y is null) return 1; // In the off chance that it causes problems with old chats, we will first compare offsets before comparing creation dates. var xOffset = x.content_offset_seconds; diff --git a/TwitchDownloaderCore/Tools/FilenameService.cs b/TwitchDownloaderCore/Tools/FilenameService.cs index 408116a1..bc89e6a4 100644 --- a/TwitchDownloaderCore/Tools/FilenameService.cs +++ b/TwitchDownloaderCore/Tools/FilenameService.cs @@ -8,20 +8,6 @@ namespace TwitchDownloaderCore.Tools { public static class FilenameService { - private static string[] GetTemplateSubfolders(ref string fullPath) - { - var returnString = fullPath.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); - fullPath = returnString[^1]; - Array.Resize(ref returnString, returnString.Length - 1); - - for (var i = 0; i < returnString.Length; i++) - { - returnString[i] = RemoveInvalidFilenameChars(returnString[i]); - } - - return returnString; - } - public static string GetFilename(string template, string title, string id, DateTime date, string channel, TimeSpan cropStart, TimeSpan cropEnd, string viewCount, string game) { var videoLength = cropEnd - cropStart; @@ -30,8 +16,8 @@ public static string GetFilename(string template, string title, string id, DateT .Replace("{title}", RemoveInvalidFilenameChars(title)) .Replace("{id}", id) .Replace("{channel}", RemoveInvalidFilenameChars(channel)) - .Replace("{date}", date.ToString("Mdyy")) - .Replace("{random_string}", Path.GetRandomFileName().Replace(".", "")) + .Replace("{date}", date.ToString("M-d-yy")) + .Replace("{random_string}", Path.GetRandomFileName().Remove(8)) // Remove the period .Replace("{crop_start}", TimeSpanHFormat.ReusableInstance.Format(@"HH\-mm\-ss", cropStart)) .Replace("{crop_end}", TimeSpanHFormat.ReusableInstance.Format(@"HH\-mm\-ss", cropEnd)) .Replace("{length}", TimeSpanHFormat.ReusableInstance.Format(@"HH\-mm\-ss", videoLength)) @@ -40,25 +26,25 @@ public static string GetFilename(string template, string title, string id, DateT if (template.Contains("{date_custom=")) { - var dateRegex = new Regex("{date_custom=\"(.*)\"}"); + var dateRegex = new Regex("{date_custom=\"(.*?)\"}"); ReplaceCustomWithFormattable(stringBuilder, dateRegex, date); } if (template.Contains("{crop_start_custom=")) { - var cropStartRegex = new Regex("{crop_start_custom=\"(.*)\"}"); + var cropStartRegex = new Regex("{crop_start_custom=\"(.*?)\"}"); ReplaceCustomWithFormattable(stringBuilder, cropStartRegex, cropStart); } if (template.Contains("{crop_end_custom=")) { - var cropEndRegex = new Regex("{crop_end_custom=\"(.*)\"}"); + var cropEndRegex = new Regex("{crop_end_custom=\"(.*?)\"}"); ReplaceCustomWithFormattable(stringBuilder, cropEndRegex, cropEnd); } if (template.Contains("{length_custom=")) { - var lengthRegex = new Regex("{length_custom=\"(.*)\"}"); + var lengthRegex = new Regex("{length_custom=\"(.*?)\"}"); ReplaceCustomWithFormattable(stringBuilder, lengthRegex, videoLength); } @@ -83,6 +69,20 @@ private static void ReplaceCustomWithFormattable(StringBuilder sb, Regex regex, } while (true); } + private static string[] GetTemplateSubfolders(ref string fullPath) + { + var returnString = fullPath.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); + fullPath = returnString[^1]; + Array.Resize(ref returnString, returnString.Length - 1); + + for (var i = 0; i < returnString.Length; i++) + { + returnString[i] = RemoveInvalidFilenameChars(returnString[i]); + } + + return returnString; + } + private static readonly char[] FilenameInvalidChars = Path.GetInvalidFileNameChars(); private static string RemoveInvalidFilenameChars(string filename) => filename.ReplaceAny(FilenameInvalidChars, '_'); diff --git a/TwitchDownloaderCore/TwitchHelper.cs b/TwitchDownloaderCore/TwitchHelper.cs index 06fc4934..d7494e91 100644 --- a/TwitchDownloaderCore/TwitchHelper.cs +++ b/TwitchDownloaderCore/TwitchHelper.cs @@ -13,6 +13,7 @@ using System.Threading; using System.Threading.Tasks; using TwitchDownloaderCore.Chat; +using TwitchDownloaderCore.Tools; using TwitchDownloaderCore.TwitchObjects; using TwitchDownloaderCore.TwitchObjects.Api; using TwitchDownloaderCore.TwitchObjects.Gql; @@ -80,7 +81,7 @@ public static async Task GetClipInfo(object clipId) return await response.Content.ReadFromJsonAsync(); } - public static async Task> GetClipLinks(string clipId) + public static async Task GetClipLinks(string clipId) { var request = new HttpRequestMessage() { @@ -91,7 +92,10 @@ public static async Task> GetClipLinks(string clipId) request.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko"); using var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); - return await response.Content.ReadFromJsonAsync>(); + + var gqlClipTokenResponses = await response.Content.ReadFromJsonAsync(); + Array.Sort(gqlClipTokenResponses[0].data.clip.videoQualities, new ClipQualityComparer()); + return gqlClipTokenResponses; } public static async Task GetGqlVideos(string channelName, string cursor = "", int limit = 50) diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipTokenResponse.cs b/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipTokenResponse.cs index 8c386137..1e909c1e 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipTokenResponse.cs +++ b/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipTokenResponse.cs @@ -1,12 +1,10 @@ -using System.Collections.Generic; - -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.TwitchObjects.Gql { public class ClipToken { public string id { get; set; } public PlaybackAccessToken playbackAccessToken { get; set; } - public List videoQualities { get; set; } + public VideoQuality[] videoQualities { get; set; } public string __typename { get; set; } } diff --git a/TwitchDownloaderTests/FilenameServiceTests.cs b/TwitchDownloaderTests/FilenameServiceTests.cs new file mode 100644 index 00000000..874f34ff --- /dev/null +++ b/TwitchDownloaderTests/FilenameServiceTests.cs @@ -0,0 +1,155 @@ +using TwitchDownloaderCore.Extensions; +using TwitchDownloaderCore.Tools; + +namespace TwitchDownloaderTests +{ + public class FilenameServiceTests + { + private static (string title, string id, DateTime date, string channel, TimeSpan cropStart, TimeSpan cropEnd, string viewCount, string game) GetExampleInfo() => + ("A Title", "abc123", new DateTime(1984, 11, 1, 9, 43, 21), "streamer8", new TimeSpan(0, 1, 2, 3, 4), new TimeSpan(0, 5, 6, 7, 8), "123456789", "A Game"); + + [Theory] + [InlineData("{title}", "A Title")] + [InlineData("{id}", "abc123")] + [InlineData("{channel}", "streamer8")] + [InlineData("{date}", "11-1-84")] + [InlineData("{crop_start}", "01-02-03")] + [InlineData("{crop_end}", "05-06-07")] + [InlineData("{length}", "04-04-04")] + [InlineData("{views}", "123456789")] + [InlineData("{game}", "A Game")] + [InlineData("{date_custom=\"s\"}", "1984-11-01T09_43_21")] + [InlineData("{crop_start_custom=\"hh\\-mm\\-ss\"}", "01-02-03")] + [InlineData("{crop_end_custom=\"hh\\-mm\\-ss\"}", "05-06-07")] + [InlineData("{length_custom=\"hh\\-mm\\-ss\"}", "04-04-04")] + public void CorrectlyGeneratesIndividualTemplates(string template, string expected) + { + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(template, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData("[{date_custom=\"M-dd-yy\"}] {channel} - {title}", "[11-01-84] streamer8 - A Title")] + [InlineData("[{channel}] [{date_custom=\"M-dd-yy\"}] [{game}] {title} ({id}) - {views} views", "[streamer8] [11-01-84] [A Game] A Title (abc123) - 123456789 views")] + [InlineData("{title} by {channel} playing {game} on {date_custom=\"M dd, yyyy\"} for {length_custom=\"h'h 'm'm 's's'\"} with {views} views", "A Title by streamer8 playing A Game on 11 01, 1984 for 4h 4m 4s with 123456789 views")] + public void CorrectlyGeneratesLargeTemplates(string template, string expected) + { + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(template, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.Equal(expected, result); + } + + [Fact] + public void CorrectlyInterpretsMultipleCustomParameters() + { + const string TEMPLATE = "{date_custom=\"yyyy\"} {date_custom=\"MM\"} {date_custom=\"dd\"} {crop_start_custom=\"hh\\-mm\\-ss\"} {crop_end_custom=\"hh\\-mm\\-ss\"} {length_custom=\"hh\\-mm\\-ss\"}"; + const string EXPECTED = "1984 11 01 01-02-03 05-06-07 04-04-04"; + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(TEMPLATE, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.Equal(EXPECTED, result); + } + + [Fact] + public void CorrectlyGeneratesSubFolders_WithForwardSlash() + { + const string TEMPLATE = "{channel}/{date_custom=\"yyyy\"}/{date_custom=\"MM\"}/{date_custom=\"dd\"}/{title}.mp4"; + var expected = Path.Combine("streamer8", "1984", "11", "01", "A Title.mp4"); + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(TEMPLATE, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.Equal(expected, result); + } + + [Fact] + public void CorrectlyGeneratesSubFolders_WithBackSlash() + { + const string TEMPLATE = "{channel}\\{date_custom=\"yyyy\"}\\{date_custom=\"MM\"}\\{date_custom=\"dd\"}\\{title}"; + var expected = Path.Combine("streamer8", "1984", "11", "01", "A Title"); + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(TEMPLATE, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData("{title}")] + [InlineData("{id}")] + [InlineData("{channel}")] + [InlineData("{views}")] + [InlineData("{game}")] + public void CorrectlyReplacesInvalidCharactersForNonCustomTemplates(string template) + { + const char EXPECTED = '_'; + var invalidChars = new string(Path.GetInvalidFileNameChars()); + + var result = FilenameService.GetFilename(template, invalidChars, invalidChars, default, invalidChars, default, default, invalidChars, invalidChars); + + Assert.All(result, c => Assert.Equal(EXPECTED, c)); + } + + [Theory] + [InlineData("{date_custom=\"'")] + [InlineData("{crop_start_custom=\"'")] + [InlineData("{crop_end_custom=\"'")] + [InlineData("{length_custom=\"'")] + public void CorrectlyReplacesInvalidCharactersForCustomTemplates(string templateStart) + { + const char EXPECTED = '_'; + var invalidChars = new string(Path.GetInvalidFileNameChars()); + var template = string.Concat( + templateStart, + invalidChars.ReplaceAny("\r\n", EXPECTED), // newline chars are not supported by the custom parameters. This will not change. + "'\"}"); + + var result = FilenameService.GetFilename(template, invalidChars, invalidChars, default, invalidChars, default, default, invalidChars, invalidChars); + + Assert.All(result, c => Assert.Equal(EXPECTED, c)); + } + + [Fact] + public void CorrectlyReplacesInvalidCharactersForSubFolders() + { + var invalidChars = new string(Path.GetInvalidPathChars()); + var template = invalidChars + "\\{title}"; + var expected = Path.Combine(new string('_', invalidChars.Length), "A Title"); + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(template, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.Equal(expected, result); + } + + [Fact] + public void RandomStringIsRandom() + { + const string TEMPLATE = "{random_string}"; + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(TEMPLATE, title, id, date, channel, cropStart, cropEnd, viewCount, game); + var result2 = FilenameService.GetFilename(TEMPLATE, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.NotEqual(result, result2); + } + + [Fact] + public void DoesNotInterpretBogusTemplateParameter() + { + const string TEMPLATE = "{foobar}"; + const string EXPECTED = "{foobar}"; + var (title, id, date, channel, cropStart, cropEnd, viewCount, game) = GetExampleInfo(); + + var result = FilenameService.GetFilename(TEMPLATE, title, id, date, channel, cropStart, cropEnd, viewCount, game); + + Assert.Equal(EXPECTED, result); + } + } +} \ No newline at end of file diff --git a/TwitchDownloaderWPF/App.xaml.cs b/TwitchDownloaderWPF/App.xaml.cs index ef31a6cb..e9b6af74 100644 --- a/TwitchDownloaderWPF/App.xaml.cs +++ b/TwitchDownloaderWPF/App.xaml.cs @@ -31,7 +31,10 @@ protected override void OnStartup(StartupEventArgs e) var windowsThemeService = new WindowsThemeService(); ThemeServiceSingleton = new ThemeService(this, windowsThemeService); - MainWindow = new MainWindow(); + MainWindow = new MainWindow + { + WindowStartupLocation = WindowStartupLocation.CenterScreen + }; MainWindow.Show(); } diff --git a/TwitchDownloaderWPF/PageChatDownload.xaml.cs b/TwitchDownloaderWPF/PageChatDownload.xaml.cs index 4ed52a29..aae2816b 100644 --- a/TwitchDownloaderWPF/PageChatDownload.xaml.cs +++ b/TwitchDownloaderWPF/PageChatDownload.xaml.cs @@ -290,7 +290,11 @@ private void btnDonate_Click(object sender, RoutedEventArgs e) private void btnSettings_Click(object sender, RoutedEventArgs e) { - WindowSettings settings = new WindowSettings(); + var settings = new WindowSettings + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; settings.ShowDialog(); btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible; } @@ -572,7 +576,11 @@ private void checkCropEnd_OnCheckStateChanged(object sender, RoutedEventArgs e) private void MenuItemEnqueue_Click(object sender, RoutedEventArgs e) { - WindowQueueOptions queueOptions = new WindowQueueOptions(this); + var queueOptions = new WindowQueueOptions(this) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; queueOptions.ShowDialog(); } diff --git a/TwitchDownloaderWPF/PageChatRender.xaml.cs b/TwitchDownloaderWPF/PageChatRender.xaml.cs index 08bd436b..df7a13a6 100644 --- a/TwitchDownloaderWPF/PageChatRender.xaml.cs +++ b/TwitchDownloaderWPF/PageChatRender.xaml.cs @@ -495,7 +495,11 @@ private void btnDonate_Click(object sender, RoutedEventArgs e) private void btnSettings_Click(object sender, RoutedEventArgs e) { SaveSettings(); - WindowSettings settings = new WindowSettings(); + var settings = new WindowSettings + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; settings.ShowDialog(); btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible; } @@ -616,7 +620,11 @@ private async void SplitBtnRender_Click(object sender, RoutedEventArgs e) if (ReferenceEquals(sender, MenuItemPartialRender)) { - WindowRangeSelect window = new WindowRangeSelect(currentRender); + var window = new WindowRangeSelect(currentRender) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; window.ShowDialog(); if (window.OK) @@ -711,7 +719,11 @@ private void MenuItemEnqueue_Click(object sender, RoutedEventArgs e) private void EnqueueRender() { - var queueOptions = new WindowQueueOptions(this); + var queueOptions = new WindowQueueOptions(this) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; queueOptions.ShowDialog(); } diff --git a/TwitchDownloaderWPF/PageChatUpdate.xaml.cs b/TwitchDownloaderWPF/PageChatUpdate.xaml.cs index 38cb7d5d..a53de865 100644 --- a/TwitchDownloaderWPF/PageChatUpdate.xaml.cs +++ b/TwitchDownloaderWPF/PageChatUpdate.xaml.cs @@ -354,7 +354,11 @@ private void btnDonate_Click(object sender, RoutedEventArgs e) private void btnSettings_Click(object sender, RoutedEventArgs e) { - WindowSettings settings = new WindowSettings(); + var settings = new WindowSettings + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; settings.ShowDialog(); btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible; } @@ -645,7 +649,11 @@ private void checkEnd_OnCheckStateChanged(object sender, RoutedEventArgs e) private void MenuItemEnqueue_Click(object sender, RoutedEventArgs e) { - WindowQueueOptions queueOptions = new WindowQueueOptions(this); + var queueOptions = new WindowQueueOptions(this) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; queueOptions.ShowDialog(); } } diff --git a/TwitchDownloaderWPF/PageClipDownload.xaml.cs b/TwitchDownloaderWPF/PageClipDownload.xaml.cs index 9c0a7fbe..b5ce848b 100644 --- a/TwitchDownloaderWPF/PageClipDownload.xaml.cs +++ b/TwitchDownloaderWPF/PageClipDownload.xaml.cs @@ -55,7 +55,7 @@ private async Task GetClipInfo() btnGetInfo.IsEnabled = false; comboQuality.Items.Clear(); Task taskClipInfo = TwitchHelper.GetClipInfo(clipId); - Task> taskLinks = TwitchHelper.GetClipLinks(clipId); + Task taskLinks = TwitchHelper.GetClipLinks(clipId); await Task.WhenAll(taskClipInfo, taskLinks); GqlClipResponse clipData = taskClipInfo.Result; @@ -178,7 +178,11 @@ private void btnDonate_Click(object sender, RoutedEventArgs e) private void btnSettings_Click(object sender, RoutedEventArgs e) { - WindowSettings settings = new WindowSettings(); + var settings = new WindowSettings + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; settings.ShowDialog(); btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible; } @@ -271,7 +275,11 @@ private void BtnCancel_Click(object sender, RoutedEventArgs e) private void MenuItemEnqueue_Click(object sender, RoutedEventArgs e) { - WindowQueueOptions queueOptions = new WindowQueueOptions(this); + var queueOptions = new WindowQueueOptions(this) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; queueOptions.ShowDialog(); } diff --git a/TwitchDownloaderWPF/PageQueue.xaml.cs b/TwitchDownloaderWPF/PageQueue.xaml.cs index d059610b..b0e2d42a 100644 --- a/TwitchDownloaderWPF/PageQueue.xaml.cs +++ b/TwitchDownloaderWPF/PageQueue.xaml.cs @@ -119,7 +119,11 @@ private void btnDonate_Click(object sender, RoutedEventArgs e) private void btnSettings_Click(object sender, RoutedEventArgs e) { - WindowSettings settings = new WindowSettings(); + var settings = new WindowSettings + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; settings.ShowDialog(); btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible; } @@ -167,19 +171,31 @@ private void numRender_ValueChanged(object sender, HandyControl.Data.FunctionEve private void btnUrlList_Click(object sender, RoutedEventArgs e) { - WindowUrlList window = new WindowUrlList(); + var window = new WindowUrlList + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; window.ShowDialog(); } private void btnVods_Click(object sender, RoutedEventArgs e) { - WindowMassDownload window = new WindowMassDownload(DownloadType.Video); + var window = new WindowMassDownload(DownloadType.Video) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; window.ShowDialog(); } private void btnClips_Click(object sender, RoutedEventArgs e) { - WindowMassDownload window = new WindowMassDownload(DownloadType.Clip); + var window = new WindowMassDownload(DownloadType.Clip) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; window.ShowDialog(); } diff --git a/TwitchDownloaderWPF/PageVodDownload.xaml.cs b/TwitchDownloaderWPF/PageVodDownload.xaml.cs index 734e0863..8e366603 100644 --- a/TwitchDownloaderWPF/PageVodDownload.xaml.cs +++ b/TwitchDownloaderWPF/PageVodDownload.xaml.cs @@ -363,7 +363,11 @@ private void btnDonate_Click(object sender, RoutedEventArgs e) private void btnSettings_Click(object sender, RoutedEventArgs e) { - WindowSettings settings = new WindowSettings(); + var settings = new WindowSettings + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; settings.ShowDialog(); btnDonate.Visibility = Settings.Default.HideDonation ? Visibility.Collapsed : Visibility.Visible; } @@ -474,7 +478,11 @@ private void MenuItemEnqueue_Click(object sender, RoutedEventArgs e) if (ValidateInputs()) { - WindowQueueOptions queueOptions = new WindowQueueOptions(this); + var queueOptions = new WindowQueueOptions(this) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; queueOptions.ShowDialog(); } else diff --git a/TwitchDownloaderWPF/WindowMassDownload.xaml.cs b/TwitchDownloaderWPF/WindowMassDownload.xaml.cs index 7c6e9514..5bf0e3d0 100644 --- a/TwitchDownloaderWPF/WindowMassDownload.xaml.cs +++ b/TwitchDownloaderWPF/WindowMassDownload.xaml.cs @@ -210,7 +210,11 @@ private void btnQueue_Click(object sender, RoutedEventArgs e) { if (selectedItems.Count > 0) { - WindowQueueOptions queue = new WindowQueueOptions(selectedItems); + var queue = new WindowQueueOptions(selectedItems) + { + Owner = this, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; if (queue.ShowDialog().GetValueOrDefault()) this.Close(); } diff --git a/TwitchDownloaderWPF/WindowUrlList.xaml.cs b/TwitchDownloaderWPF/WindowUrlList.xaml.cs index 714c6e0e..fd05c7f3 100644 --- a/TwitchDownloaderWPF/WindowUrlList.xaml.cs +++ b/TwitchDownloaderWPF/WindowUrlList.xaml.cs @@ -156,7 +156,11 @@ private async void btnQueue_Click(object sender, RoutedEventArgs e) return; } - WindowQueueOptions queue = new WindowQueueOptions(dataList); + var queue = new WindowQueueOptions(dataList) + { + Owner = this, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; if (queue.ShowDialog().GetValueOrDefault()) this.Close();