From 0c692abf29ce4b77699f53a5261784f0fdefeb91 Mon Sep 17 00:00:00 2001 From: Allex Rodrigues Date: Sun, 1 Nov 2020 21:21:27 -0300 Subject: [PATCH 01/10] Adding steam grid images download when exporting games --- UWPHook.sln | 8 -- UWPHook/Crc32.cs | 48 +++++++++++ UWPHook/GamesWindow.xaml.cs | 104 +++++++++++++++++++++--- UWPHook/SteamGridDb/GameResponse.cs | 10 +++ UWPHook/SteamGridDb/GridResponse.cs | 13 +++ UWPHook/SteamGridDb/HeroResponse.cs | 7 ++ UWPHook/SteamGridDb/LogoResponse.cs | 7 ++ UWPHook/SteamGridDb/SteamGridDbApi.cs | 111 ++++++++++++++++++++++++++ UWPHook/UWPHook.csproj | 12 +++ UWPHook/packages.config | 2 + 10 files changed, 303 insertions(+), 19 deletions(-) create mode 100644 UWPHook/Crc32.cs create mode 100644 UWPHook/SteamGridDb/GameResponse.cs create mode 100644 UWPHook/SteamGridDb/GridResponse.cs create mode 100644 UWPHook/SteamGridDb/HeroResponse.cs create mode 100644 UWPHook/SteamGridDb/LogoResponse.cs create mode 100644 UWPHook/SteamGridDb/SteamGridDbApi.cs diff --git a/UWPHook.sln b/UWPHook.sln index 8a1bd6d..6a1fd6c 100644 --- a/UWPHook.sln +++ b/UWPHook.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 15.0.27703.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWPHook", "UWPHook\UWPHook.csproj", "{AFE09BCF-28A4-48EE-876B-FEF080D04D5F}" EndProject -Project("{840C416C-B8F3-42BC-B0DD-F6BB14C9F8CB}") = "Setup", "Setup\Setup.aiproj", "{F63C6051-9812-47BE-87F2-ECA8F2E89EC0}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,12 +18,6 @@ Global {AFE09BCF-28A4-48EE-876B-FEF080D04D5F}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU {AFE09BCF-28A4-48EE-876B-FEF080D04D5F}.Release|Any CPU.ActiveCfg = Release|Any CPU {AFE09BCF-28A4-48EE-876B-FEF080D04D5F}.Release|Any CPU.Build.0 = Release|Any CPU - {F63C6051-9812-47BE-87F2-ECA8F2E89EC0}.Debug|Any CPU.ActiveCfg = DefaultBuild - {F63C6051-9812-47BE-87F2-ECA8F2E89EC0}.Debug|Any CPU.Build.0 = DefaultBuild - {F63C6051-9812-47BE-87F2-ECA8F2E89EC0}.DefaultBuild|Any CPU.ActiveCfg = DefaultBuild - {F63C6051-9812-47BE-87F2-ECA8F2E89EC0}.DefaultBuild|Any CPU.Build.0 = DefaultBuild - {F63C6051-9812-47BE-87F2-ECA8F2E89EC0}.Release|Any CPU.ActiveCfg = DefaultBuild - {F63C6051-9812-47BE-87F2-ECA8F2E89EC0}.Release|Any CPU.Build.0 = DefaultBuild EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/UWPHook/Crc32.cs b/UWPHook/Crc32.cs new file mode 100644 index 0000000..7cf768f --- /dev/null +++ b/UWPHook/Crc32.cs @@ -0,0 +1,48 @@ +using System; + +namespace UWPHook +{ + public class Crc32 + { + uint[] table; + + public uint ComputeChecksum(byte[] bytes) + { + uint crc = 0xffffffff; + for (int i = 0; i < bytes.Length; ++i) + { + byte index = (byte)(((crc) & 0xff) ^ bytes[i]); + crc = (uint)((crc >> 8) ^ table[index]); + } + return ~crc; + } + + public byte[] ComputeChecksumBytes(byte[] bytes) + { + return BitConverter.GetBytes(ComputeChecksum(bytes)); + } + + public Crc32() + { + uint poly = 0xedb88320; + table = new uint[256]; + uint temp = 0; + for (uint i = 0; i < table.Length; ++i) + { + temp = i; + for (int j = 8; j > 0; --j) + { + if ((temp & 1) == 1) + { + temp = (uint)((temp >> 1) ^ poly); + } + else + { + temp >>= 1; + } + } + table[i] = temp; + } + } + } +} diff --git a/UWPHook/GamesWindow.xaml.cs b/UWPHook/GamesWindow.xaml.cs index 1d41e4d..d3d3672 100644 --- a/UWPHook/GamesWindow.xaml.cs +++ b/UWPHook/GamesWindow.xaml.cs @@ -2,12 +2,17 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Drawing; +using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Linq; +using System.Net; +using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; +using UWPHook.SteamGridDb; using VDFParser; using VDFParser.Models; @@ -96,7 +101,7 @@ namespace UWPHook { if (Properties.Settings.Default.ChangeLanguage && !String.IsNullOrEmpty(Properties.Settings.Default.TargetLanguage)) { - ScriptManager.RunScript("Set - WinUILanguageOverride " + currentLanguage); + ScriptManager.RunScript("Set-WinUILanguageOverride " + currentLanguage); } //The user has probably finished using the app, so let's close UWPHook to keep the experience clean @@ -104,25 +109,97 @@ namespace UWPHook } } - private void ExportButton_Click(object sender, RoutedEventArgs e) + private UInt64 GenerateSteamGridAppId(string appName, string appTarget) { - bwrSave = new BackgroundWorker(); - bwrSave.DoWork += BwrSave_DoWork; - bwrSave.RunWorkerCompleted += BwrSave_RunWorkerCompleted; - grid.IsEnabled = false; - progressBar.Visibility = Visibility.Visible; + byte[] nameTargetBytes = Encoding.UTF8.GetBytes(appTarget + appName + ""); + UInt64 crc = new Crc32().ComputeChecksum(nameTargetBytes); + UInt64 gameId = crc | 0x80000000; - bwrSave.RunWorkerAsync(); + return gameId; } - private void BwrSave_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + private async void ExportButton_Click(object sender, RoutedEventArgs e) { + grid.IsEnabled = false; + progressBar.Visibility = Visibility.Visible; + + await ExportGames(); + grid.IsEnabled = true; progressBar.Visibility = Visibility.Collapsed; MessageBox.Show("Your apps were successfuly exported, please restart Steam in order to see your apps.", "UWPHook", MessageBoxButton.OK, MessageBoxImage.Information); } - private void BwrSave_DoWork(object sender, DoWorkEventArgs e) + private void SaveImage(string imageUrl, string destinationFilename, ImageFormat format) + { + WebClient client = new WebClient(); + Stream stream = client.OpenRead(imageUrl); + Bitmap bitmap; bitmap = new Bitmap(stream); + + if (bitmap != null) + { + bitmap.Save(destinationFilename, format); + } + + stream.Flush(); + stream.Close(); + client.Dispose(); + } + + private async Task DownloadGridImages(string userId, string appName, string appTarget) + { + // Generate app id for grid images + SteamGridDbApi api = new SteamGridDbApi("0973373b2cec3120ce673d06747d506c"); + string gridDirectory = userId + @"\\config\\grid\\"; + + var games = await api.SearchGame(appName); + + if (games != null) + { + var game = games[0]; + UInt64 gameId = GenerateSteamGridAppId(appName, appTarget); + + if (!Directory.Exists(gridDirectory)) + { + Directory.CreateDirectory(gridDirectory); + } + + var gameGrids = api.GetGameGrids(game.Id, "600x900", "static"); + var gameHeroes = api.GetGameHeroes(game.Id, "static"); + var gameLogos = api.GetGameLogos(game.Id, "static"); + + await Task.WhenAll( + gameGrids, + gameHeroes, + gameLogos + ); + + var grids = await gameGrids; + var heroes = await gameHeroes; + var logos = await gameLogos; + + if (grids != null) + { + var grid = grids[0]; + SaveImage(grid.Url, $"{gridDirectory}\\{gameId}p.png", ImageFormat.Png); + } + + if (heroes != null) + { + var hero = heroes[0]; + SaveImage(hero.Url, $"{gridDirectory}\\{gameId}_hero.png", ImageFormat.Png); + } + + if (logos != null) + { + var logo = logos[0]; + SaveImage(logo.Url, $"{gridDirectory}\\{gameId}_logo.png", ImageFormat.Png); + } + + } + } + + private async Task ExportGames() { string steam_folder = SteamManager.GetSteamFolder(); if (Directory.Exists(steam_folder)) @@ -158,10 +235,12 @@ namespace UWPHook { foreach (var app in selected_apps) { + string appTarget = @"""" + System.Reflection.Assembly.GetExecutingAssembly().Location + @""" " + app.Aumid; + VDFEntry newApp = new VDFEntry() { AppName = app.Name, - Exe = @"""" + System.Reflection.Assembly.GetExecutingAssembly().Location + @""" " + app.Aumid, + Exe = appTarget, StartDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), AllowDesktopConfig = 1, Icon = app.Icon, @@ -178,6 +257,9 @@ namespace UWPHook //Resize this array so it fits the new entries Array.Resize(ref shortcuts, shortcuts.Length + 1); shortcuts[shortcuts.Length - 1] = newApp; + + // TODO: Check if api key setting exist + await DownloadGridImages(user, app.Name, appTarget); } try diff --git a/UWPHook/SteamGridDb/GameResponse.cs b/UWPHook/SteamGridDb/GameResponse.cs new file mode 100644 index 0000000..daafef5 --- /dev/null +++ b/UWPHook/SteamGridDb/GameResponse.cs @@ -0,0 +1,10 @@ +namespace UWPHook.SteamGridDb +{ + class GameResponse + { + + public int Id { get; set; } + public string Name { get; set; } + + } +} diff --git a/UWPHook/SteamGridDb/GridResponse.cs b/UWPHook/SteamGridDb/GridResponse.cs new file mode 100644 index 0000000..0f39b6e --- /dev/null +++ b/UWPHook/SteamGridDb/GridResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UWPHook.SteamGridDb +{ + class GridResponse + { + public string Url { get; set; } + } +} diff --git a/UWPHook/SteamGridDb/HeroResponse.cs b/UWPHook/SteamGridDb/HeroResponse.cs new file mode 100644 index 0000000..80c38ad --- /dev/null +++ b/UWPHook/SteamGridDb/HeroResponse.cs @@ -0,0 +1,7 @@ +namespace UWPHook.SteamGridDb +{ + public class HeroResponse + { + public string Url { get; set; } + } +} \ No newline at end of file diff --git a/UWPHook/SteamGridDb/LogoResponse.cs b/UWPHook/SteamGridDb/LogoResponse.cs new file mode 100644 index 0000000..258f072 --- /dev/null +++ b/UWPHook/SteamGridDb/LogoResponse.cs @@ -0,0 +1,7 @@ +namespace UWPHook.SteamGridDb +{ + public class LogoResponse + { + public string Url { get; set; } + } +} \ No newline at end of file diff --git a/UWPHook/SteamGridDb/SteamGridDbApi.cs b/UWPHook/SteamGridDb/SteamGridDbApi.cs new file mode 100644 index 0000000..715e634 --- /dev/null +++ b/UWPHook/SteamGridDb/SteamGridDbApi.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; + +namespace UWPHook.SteamGridDb +{ + class SteamGridDbApi + { + private const string BASE_URL = "https://www.steamgriddb.com/api/v2/"; + + private HttpClient httpClient; + + public SteamGridDbApi(string apiKey) + { + httpClient = new HttpClient(); + httpClient.BaseAddress = new Uri(BASE_URL); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); + } + + public async Task SearchGame(string gameName) + { + string path = $"search/autocomplete/{gameName}"; + + GameResponse[] games = null; + HttpResponseMessage response = await httpClient.GetAsync(path); + + if(response.IsSuccessStatusCode) + { + var parsedResponse = await response.Content.ReadAsAsync>(); + games = parsedResponse.Data; + } + + return games; + } + + public async Task GetGameGrids( + int gameId, + string dimensions = null, + string types = null, + string styles = null, + string nsfw = "any", + string humor = "any") + { + string path = $"grids/game/{gameId}"; + + GridResponse[] grids = null; + HttpResponseMessage response = await httpClient.GetAsync(path); + + if (response.IsSuccessStatusCode) + { + var parsedResponse = await response.Content.ReadAsAsync>(); + grids = parsedResponse.Data; + } + + return grids; + } + + public async Task GetGameHeroes( + int gameId, + string types = null, + string dimensions = null, + string styles = null, + string nsfw = "any", + string humor = "any") + { + string path = $"heroes/game/{gameId}"; + + HeroResponse[] heroes = null; + HttpResponseMessage response = await httpClient.GetAsync(path); + + if (response.IsSuccessStatusCode) + { + var parsedResponse = await response.Content.ReadAsAsync>(); + heroes = parsedResponse.Data; + } + + return heroes; + } + + public async Task GetGameLogos( + int gameId, + string types = null, + string styles = null, + string nsfw = "any", + string humor = "any") + { + string path = $"logos/game/{gameId}"; + + LogoResponse[] logos = null; + HttpResponseMessage response = await httpClient.GetAsync(path); + + if (response.IsSuccessStatusCode) + { + var parsedResponse = await response.Content.ReadAsAsync>(); + logos = parsedResponse.Data; + } + + return logos; + } + + private class ResponseWrapper + { + public bool Success { get; set; } + public T[] Data { get; set; } + } + } +} diff --git a/UWPHook/UWPHook.csproj b/UWPHook/UWPHook.csproj index 65a6e5e..7ac201b 100644 --- a/UWPHook/UWPHook.csproj +++ b/UWPHook/UWPHook.csproj @@ -65,6 +65,9 @@ ..\packages\MaterialDesignThemes.3.1.3\lib\net45\MaterialDesignThemes.Wpf.dll + + ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + ..\..\SharpSteam\SharpSteam\bin\Release\SharpSteam.dll @@ -74,6 +77,9 @@ ..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll + @@ -97,6 +103,7 @@ + FullScreenLauncher.xaml @@ -108,6 +115,11 @@ SettingsWindow.xaml + + + + + MSBuild:Compile diff --git a/UWPHook/packages.config b/UWPHook/packages.config index a0c4728..b43367d 100644 --- a/UWPHook/packages.config +++ b/UWPHook/packages.config @@ -2,6 +2,8 @@ + + \ No newline at end of file From ef186c5b94a60a9be272dc6028ad53aac15aef3a Mon Sep 17 00:00:00 2001 From: Allex Rodrigues Date: Sun, 1 Nov 2020 22:03:30 -0300 Subject: [PATCH 02/10] Adding landscape grid image variant --- UWPHook/GamesWindow.xaml.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/UWPHook/GamesWindow.xaml.cs b/UWPHook/GamesWindow.xaml.cs index d3d3672..5ea014e 100644 --- a/UWPHook/GamesWindow.xaml.cs +++ b/UWPHook/GamesWindow.xaml.cs @@ -164,23 +164,32 @@ namespace UWPHook Directory.CreateDirectory(gridDirectory); } - var gameGrids = api.GetGameGrids(game.Id, "600x900", "static"); + var gameGridsVertical = api.GetGameGrids(game.Id, "600x900", "static"); + var gameGridsHorizontal = api.GetGameGrids(game.Id, "460x215", "static"); var gameHeroes = api.GetGameHeroes(game.Id, "static"); var gameLogos = api.GetGameLogos(game.Id, "static"); await Task.WhenAll( - gameGrids, + gameGridsVertical, + gameGridsHorizontal, gameHeroes, gameLogos ); - var grids = await gameGrids; + var gridsVertical = await gameGridsVertical; + var gridsHorizontal = await gameGridsHorizontal; var heroes = await gameHeroes; var logos = await gameLogos; - if (grids != null) + if (gridsHorizontal != null) { - var grid = grids[0]; + var grid = gridsHorizontal[0]; + SaveImage(grid.Url, $"{gridDirectory}\\{gameId}.png", ImageFormat.Png); + } + + if (gridsVertical != null) + { + var grid = gridsVertical[0]; SaveImage(grid.Url, $"{gridDirectory}\\{gameId}p.png", ImageFormat.Png); } From e499b0a992c139fdd4073e6bf6f889d9ef372002 Mon Sep 17 00:00:00 2001 From: Allex Rodrigues Date: Sun, 1 Nov 2020 22:03:55 -0300 Subject: [PATCH 03/10] Fix steamgriddb api calls not sending query params --- UWPHook/SteamGridDb/SteamGridDbApi.cs | 48 +++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/UWPHook/SteamGridDb/SteamGridDbApi.cs b/UWPHook/SteamGridDb/SteamGridDbApi.cs index 715e634..632cda5 100644 --- a/UWPHook/SteamGridDb/SteamGridDbApi.cs +++ b/UWPHook/SteamGridDb/SteamGridDbApi.cs @@ -45,7 +45,22 @@ namespace UWPHook.SteamGridDb string nsfw = "any", string humor = "any") { - string path = $"grids/game/{gameId}"; + string path = $"grids/game/{gameId}?"; + + if (!String.IsNullOrEmpty(dimensions)) + path += $"dimensions={dimensions}&"; + + if (!String.IsNullOrEmpty(types)) + path += $"types={types}&"; + + if (!String.IsNullOrEmpty(styles)) + path += $"styles={styles}&"; + + if (!String.IsNullOrEmpty(nsfw)) + path += $"nsfw={nsfw}&"; + + if (!String.IsNullOrEmpty(humor)) + path += $"humor={humor}&"; GridResponse[] grids = null; HttpResponseMessage response = await httpClient.GetAsync(path); @@ -67,7 +82,22 @@ namespace UWPHook.SteamGridDb string nsfw = "any", string humor = "any") { - string path = $"heroes/game/{gameId}"; + string path = $"heroes/game/{gameId}?"; + + if (!String.IsNullOrEmpty(dimensions)) + path += $"dimensions={dimensions}&"; + + if (!String.IsNullOrEmpty(types)) + path += $"types={types}&"; + + if (!String.IsNullOrEmpty(styles)) + path += $"styles={styles}&"; + + if (!String.IsNullOrEmpty(nsfw)) + path += $"nsfw={nsfw}&"; + + if (!String.IsNullOrEmpty(humor)) + path += $"humor={humor}&"; HeroResponse[] heroes = null; HttpResponseMessage response = await httpClient.GetAsync(path); @@ -88,7 +118,19 @@ namespace UWPHook.SteamGridDb string nsfw = "any", string humor = "any") { - string path = $"logos/game/{gameId}"; + string path = $"logos/game/{gameId}?"; + + if (!String.IsNullOrEmpty(types)) + path += $"types={types}&"; + + if (!String.IsNullOrEmpty(styles)) + path += $"styles={styles}&"; + + if (!String.IsNullOrEmpty(nsfw)) + path += $"nsfw={nsfw}&"; + + if (!String.IsNullOrEmpty(humor)) + path += $"humor={humor}&"; LogoResponse[] logos = null; HttpResponseMessage response = await httpClient.GetAsync(path); From 90718a3fa46dbc4004f19746faa89705d45f49ad Mon Sep 17 00:00:00 2001 From: Allex Rodrigues Date: Sun, 1 Nov 2020 22:04:07 -0300 Subject: [PATCH 04/10] Add api key field to settings screen --- UWPHook/App.config | 5 +++- UWPHook/GamesWindow.xaml.cs | 9 +++---- UWPHook/Properties/Settings.Designer.cs | 14 ++++++++++- UWPHook/Properties/Settings.settings | 3 +++ UWPHook/SettingsWindow.xaml | 32 +++++++++++++++---------- UWPHook/SettingsWindow.xaml.cs | 2 ++ 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/UWPHook/App.config b/UWPHook/App.config index c80186b..f9ab9ff 100644 --- a/UWPHook/App.config +++ b/UWPHook/App.config @@ -14,7 +14,7 @@ False - + 5 @@ -22,6 +22,9 @@ False + + + diff --git a/UWPHook/GamesWindow.xaml.cs b/UWPHook/GamesWindow.xaml.cs index 5ea014e..d3abaad 100644 --- a/UWPHook/GamesWindow.xaml.cs +++ b/UWPHook/GamesWindow.xaml.cs @@ -148,8 +148,7 @@ namespace UWPHook private async Task DownloadGridImages(string userId, string appName, string appTarget) { - // Generate app id for grid images - SteamGridDbApi api = new SteamGridDbApi("0973373b2cec3120ce673d06747d506c"); + SteamGridDbApi api = new SteamGridDbApi(Properties.Settings.Default.SteamGridDbApiKey); string gridDirectory = userId + @"\\config\\grid\\"; var games = await api.SearchGame(appName); @@ -267,8 +266,10 @@ namespace UWPHook Array.Resize(ref shortcuts, shortcuts.Length + 1); shortcuts[shortcuts.Length - 1] = newApp; - // TODO: Check if api key setting exist - await DownloadGridImages(user, app.Name, appTarget); + if (!String.IsNullOrEmpty(Properties.Settings.Default.SteamGridDbApiKey)) + { + await DownloadGridImages(user, app.Name, appTarget); + } } try diff --git a/UWPHook/Properties/Settings.Designer.cs b/UWPHook/Properties/Settings.Designer.cs index 7a982ca..fc330f9 100644 --- a/UWPHook/Properties/Settings.Designer.cs +++ b/UWPHook/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace UWPHook.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")] public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -70,5 +70,17 @@ namespace UWPHook.Properties { this["StreamMode"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string SteamGridDbApiKey { + get { + return ((string)(this["SteamGridDbApiKey"])); + } + set { + this["SteamGridDbApiKey"] = value; + } + } } } diff --git a/UWPHook/Properties/Settings.settings b/UWPHook/Properties/Settings.settings index 6aed1ad..339d33b 100644 --- a/UWPHook/Properties/Settings.settings +++ b/UWPHook/Properties/Settings.settings @@ -14,5 +14,8 @@ False + + + \ No newline at end of file diff --git a/UWPHook/SettingsWindow.xaml b/UWPHook/SettingsWindow.xaml index 383fc72..c79692c 100644 --- a/UWPHook/SettingsWindow.xaml +++ b/UWPHook/SettingsWindow.xaml @@ -26,9 +26,12 @@ - - - + + + + + + @@ -39,16 +42,19 @@ - -