From 60ea0145fd825b8edd5cc2ea154c9946a43b0434 Mon Sep 17 00:00:00 2001 From: jliddev Date: Wed, 5 Aug 2020 12:57:45 -0500 Subject: [PATCH] v1.14.2 Add in global addon channel selection --- .../Services/Contracts/IWowUpService.cs | 3 + WowUp.WPF/Assets/changelog.json | 4 + WowUp.WPF/Extensions/AddonExtensions.cs | 17 +++ WowUp.WPF/Extensions/EnumExtensions.cs | 22 +++ WowUp.WPF/Services/AddonService.cs | 128 +++++++----------- WowUp.WPF/Services/WowUpService.cs | 45 ++++-- WowUp.WPF/ViewModels/OptionsViewModel.cs | 30 +++- WowUp.WPF/Views/OptionsView.xaml | 20 ++- WowUp.WPF/WowUp.WPF.csproj | 3 +- 9 files changed, 179 insertions(+), 93 deletions(-) create mode 100644 WowUp.WPF/Extensions/EnumExtensions.cs diff --git a/WowUp.Common/Services/Contracts/IWowUpService.cs b/WowUp.Common/Services/Contracts/IWowUpService.cs index 54e08676..b3e447ba 100644 --- a/WowUp.Common/Services/Contracts/IWowUpService.cs +++ b/WowUp.Common/Services/Contracts/IWowUpService.cs @@ -18,7 +18,10 @@ namespace WowUp.Common.Services.Contracts Task GetChangeLogFile(); Task UpdateApplication(Action updateAction); + bool GetCollapseToTray(); void SetCollapseToTray(bool enabled); + AddonChannelType GetDefaultAddonChannel(); + void SetDefaultAddonChannel(AddonChannelType type); } } diff --git a/WowUp.WPF/Assets/changelog.json b/WowUp.WPF/Assets/changelog.json index 42177262..a7590d7a 100644 --- a/WowUp.WPF/Assets/changelog.json +++ b/WowUp.WPF/Assets/changelog.json @@ -1,5 +1,9 @@ { "ChangeLogs": [ + { + "Version": "1.14.2", + "Description": "Add the ability to set a global addon channel." + }, { "Version": "1.14.1", "Description": "Fix issue with update button being shown over progress bar during auto update." diff --git a/WowUp.WPF/Extensions/AddonExtensions.cs b/WowUp.WPF/Extensions/AddonExtensions.cs index a912cd0a..77314493 100644 --- a/WowUp.WPF/Extensions/AddonExtensions.cs +++ b/WowUp.WPF/Extensions/AddonExtensions.cs @@ -7,6 +7,23 @@ namespace WowUp.WPF.Extensions { public static class AddonExtensions { + public static Addon Assign(this Addon addon1, Addon addon2) + { + addon1.Name = addon2.Name; + addon1.FolderName = addon2.FolderName; + addon1.DownloadUrl = addon2.DownloadUrl; + addon1.LatestVersion = addon2.LatestVersion; + addon1.ExternalId = addon2.ExternalId; + addon1.ProviderName = addon2.ProviderName; + addon1.ExternalUrl = addon2.ExternalUrl; + addon1.ThumbnailUrl = addon2.ThumbnailUrl; + addon1.GameVersion = addon2.GameVersion; + addon1.ClientType = addon2.ClientType; + addon1.ChannelType = addon2.ChannelType; + + return addon1; + } + public static IList GetInstalledDirectories(this Addon addon) { if (string.IsNullOrEmpty(addon.InstalledFolders)) diff --git a/WowUp.WPF/Extensions/EnumExtensions.cs b/WowUp.WPF/Extensions/EnumExtensions.cs new file mode 100644 index 00000000..29c69bbf --- /dev/null +++ b/WowUp.WPF/Extensions/EnumExtensions.cs @@ -0,0 +1,22 @@ +using System; +using WowUp.Common.Enums; + +namespace WowUp.WPF.Extensions +{ + public static class EnumExtensions + { + public static AddonChannelType ToAddonChannelType(this string str) + { + if (AddonChannelType.Alpha.ToString().Equals(str, StringComparison.OrdinalIgnoreCase)) + { + return AddonChannelType.Alpha; + } + else if (AddonChannelType.Beta.ToString().Equals(str, StringComparison.OrdinalIgnoreCase)) + { + return AddonChannelType.Beta; + } + + return AddonChannelType.Stable; + } + } +} diff --git a/WowUp.WPF/Services/AddonService.cs b/WowUp.WPF/Services/AddonService.cs index d4246397..bd9d3ed9 100644 --- a/WowUp.WPF/Services/AddonService.cs +++ b/WowUp.WPF/Services/AddonService.cs @@ -33,9 +33,11 @@ namespace WowUp.WPF.Services protected readonly IEnumerable _providers = new List(); protected readonly IAddonRepository _addonRepository; + protected readonly IAnalyticsService _analyticsService; protected readonly IDownloadService _downloadService; protected readonly IWarcraftService _warcraftService; + protected readonly IWowUpService _wowUpService; public event AddonEventHandler AddonUninstalled; public event AddonEventHandler AddonInstalled; @@ -48,12 +50,15 @@ namespace WowUp.WPF.Services IAddonRepository addonRepository, IAnalyticsService analyticsService, IDownloadService downloadSevice, - IWarcraftService warcraftService) + IWarcraftService warcraftService, + IWowUpService wowUpService) { _addonRepository = addonRepository; + _analyticsService = analyticsService; _downloadService = downloadSevice; _warcraftService = warcraftService; + _wowUpService = wowUpService; _providers = new List { @@ -177,29 +182,6 @@ namespace WowUp.WPF.Services .FirstOrDefault(); } - public async Task InstallAddon( - PotentialAddon potentialAddon, - WowClientType clientType, - Action onUpdate = null) - { - var provider = _providers.First(p => p.Name == potentialAddon.ProviderName); - var searchResult = await provider.GetById(potentialAddon.ExternalId, clientType); - var latestFile = GetLatestFile(searchResult, AddonChannelType.Stable); - - var existingAddon = _addonRepository.GetByExternalId(searchResult.ExternalId, clientType); - - if (existingAddon != null) - { - throw new AddonAlreadyInstalledException(); - } - - var addon = CreateAddon(latestFile.Folders.FirstOrDefault(), searchResult, latestFile, clientType); - - _addonRepository.SaveItem(addon); - - await InstallAddon(addon.Id, onUpdate); - } - public async Task GetAddonByUri( Uri addonUri, WowClientType clientType, @@ -208,25 +190,6 @@ namespace WowUp.WPF.Services var provider = GetAddonProvider(addonUri); return await provider.Search(addonUri, clientType); - - //var latestFile = GetLatestFile(searchResult, AddonChannelType.Stable); - //if (latestFile == null) - //{ - // throw new AddonNotFoundException(); - //} - - //var existingAddon = _addonRepository.GetByExternalId(searchResult.ExternalId, clientType); - - //if(existingAddon != null) - //{ - // throw new AddonAlreadyInstalledException(); - //} - - //var addon = CreateAddon(latestFile.Folders.FirstOrDefault(), searchResult, latestFile, clientType); - - //_addonRepository.SaveItem(addon); - - //await InstallAddon(addon.Id, onUpdate); } public async Task UninstallAddon(Addon addon) @@ -245,6 +208,41 @@ namespace WowUp.WPF.Services AddonUninstalled?.Invoke(this, new AddonEventArgs(addon, AddonChangeType.Uninstalled)); } + public async Task GetAddon( + string externalId, + string providerName, + WowClientType clientType) + { + var provider = GetProvider(providerName); + var searchResult = await provider.GetById(externalId, clientType); + var latestFile = GetLatestFile(searchResult, _wowUpService.GetDefaultAddonChannel()); + + return CreateAddon(latestFile.Folders.FirstOrDefault(), searchResult, latestFile, clientType); + } + + private IAddonProvider GetProvider(string providerName) + { + return _providers.First(p => p.Name == providerName); + } + + public async Task InstallAddon( + PotentialAddon potentialAddon, + WowClientType clientType, + Action onUpdate = null) + { + var existingAddon = _addonRepository.GetByExternalId(potentialAddon.ExternalId, clientType); + if (existingAddon != null) + { + throw new AddonAlreadyInstalledException(); + } + + var addon = await GetAddon(potentialAddon.ExternalId, potentialAddon.ProviderName, clientType); + + _addonRepository.SaveItem(addon); + + await InstallAddon(addon.Id, onUpdate); + } + public async Task InstallAddon(int addonId, Action updateAction) { var addon = GetAddon(addonId); @@ -253,6 +251,12 @@ namespace WowUp.WPF.Services throw new Exception("Addon not found or invalid"); } + if(addon.ChannelType != _wowUpService.GetDefaultAddonChannel()) + { + var newAddon = await GetAddon(addon.ExternalId, addon.ProviderName, addon.ClientType); + addon.Assign(newAddon); + } + updateAction?.Invoke(AddonInstallState.Downloading, 25m); string downloadedFilePath = string.Empty; @@ -380,40 +384,6 @@ namespace WowUp.WPF.Services return await MapAll(addonFolders, clientType); } - //public async Task> MapAll(IEnumerable addons, WowClientType clientType) - //{ - // if (addons == null) - // { - // Log.Warning("Addon list was null"); - // return new List(); - // } - - // foreach (var addon in addons) - // { - // Log.Debug($"Addon {addon.FolderName}"); - - // try - // { - // var searchResults = await Search(addon.Name, addon.FolderName, clientType); - // var firstResult = searchResults.FirstOrDefault(); - // if (firstResult == null) - // { - // continue; - // } - - // addon.LatestVersion = firstResult.Version; - // addon.GameVersion = firstResult.GameVersion; - // addon.Author = firstResult.Author; - // } - // catch (Exception ex) - // { - // Log.Error(ex, "Failed to map addon"); - // } - // } - - // return addons.ToList(); - //} - public async Task> MapAll(IEnumerable addonFolders, WowClientType clientType) { var results = new Dictionary(); @@ -427,7 +397,7 @@ namespace WowUp.WPF.Services { var provider = _providers.First(p => p is CurseAddonProvider) as CurseAddonProvider; var searchResult = await provider.GetById(addonFolder.Toc.CurseProjectId, clientType); - var latestFile = GetLatestFile(searchResult, AddonChannelType.Stable); + var latestFile = GetLatestFile(searchResult, _wowUpService.GetDefaultAddonChannel()); addon = CreateAddon(addonFolder.Name, searchResult, latestFile, clientType); } else @@ -522,7 +492,7 @@ namespace WowUp.WPF.Services DownloadUrl = latestFile.DownloadUrl, ExternalUrl = searchResult.ExternalUrl, ProviderName = searchResult.ProviderName, - ChannelType = latestFile.ChannelType + ChannelType = _wowUpService.GetDefaultAddonChannel() }; } } diff --git a/WowUp.WPF/Services/WowUpService.cs b/WowUp.WPF/Services/WowUpService.cs index 01fb72a0..8c6dbf94 100644 --- a/WowUp.WPF/Services/WowUpService.cs +++ b/WowUp.WPF/Services/WowUpService.cs @@ -21,22 +21,20 @@ namespace WowUp.WPF.Services private const string LatestVersionUrlFormat = "https://wowup-builds.s3.us-east-2.amazonaws.com/v{0}/WowUp.zip"; private const string ChangeLogFileCacheKey = "change_log_file"; private const string CollapseToTrayKey = "collapse_to_tray"; + private const string DefaultAddonChannelKey = "default_addon_channel"; public const string WebsiteUrl = "https://wowup.io"; private readonly IMemoryCache _cache; - private readonly IDownloadService _downloadSevice; private readonly IServiceProvider _serviceProvider; private readonly IPreferenceRepository _preferenceRepository; public WowUpService( IMemoryCache memoryCache, IPreferenceRepository preferenceRepository, - IServiceProvider serviceProvider, - IDownloadService downloadService) + IServiceProvider serviceProvider) { _cache = memoryCache; - _downloadSevice = downloadService; _serviceProvider = serviceProvider; _preferenceRepository = preferenceRepository; @@ -56,13 +54,34 @@ namespace WowUp.WPF.Services public void SetCollapseToTray(bool enabled) { - var pref = _preferenceRepository.FindByKey(CollapseToTrayKey); - if (pref == null) + SetPreference(CollapseToTrayKey, enabled.ToString()); + } + + public AddonChannelType GetDefaultAddonChannel() + { + var pref = _preferenceRepository.FindByKey(DefaultAddonChannelKey); + if(pref == null) { - pref = new Preference { Key = CollapseToTrayKey }; + throw new Exception("Default addon channel preference not found"); } - pref.Value = enabled.ToString(); + return pref.Value.ToAddonChannelType(); + } + + public void SetDefaultAddonChannel(AddonChannelType type) + { + SetPreference(DefaultAddonChannelKey, type.ToString()); + } + + public void SetPreference(string key, string value) + { + var pref = _preferenceRepository.FindByKey(key); + if (pref == null) + { + pref = new Preference { Key = key }; + } + + pref.Value = value; _preferenceRepository.SaveItem(pref); } @@ -90,7 +109,7 @@ namespace WowUp.WPF.Services public async Task GetLatestVersion() { var changeLogFile = await GetChangeLogFile(); - if(changeLogFile == null) + if (changeLogFile == null) { return string.Empty; } @@ -153,8 +172,14 @@ namespace WowUp.WPF.Services { SetCollapseToTray(true); } + + pref = _preferenceRepository.FindByKey(DefaultAddonChannelKey); + if (pref == null) + { + SetDefaultAddonChannel(AddonChannelType.Stable); + } } - + } } diff --git a/WowUp.WPF/ViewModels/OptionsViewModel.cs b/WowUp.WPF/ViewModels/OptionsViewModel.cs index 58ee6d0e..46d4ab87 100644 --- a/WowUp.WPF/ViewModels/OptionsViewModel.cs +++ b/WowUp.WPF/ViewModels/OptionsViewModel.cs @@ -1,4 +1,6 @@ -using WowUp.Common.Enums; +using System.Collections.ObjectModel; +using System.Windows.Controls; +using WowUp.Common.Enums; using WowUp.Common.Services.Contracts; using WowUp.WPF.Services.Contracts; using WowUp.WPF.Utilities; @@ -60,6 +62,13 @@ namespace WowUp.WPF.ViewModels set { SetProperty(ref _collapseToTrayEnabled, value); } } + private AddonChannelType _selectedAddonChannelType; + public AddonChannelType SelectedAddonChannelType + { + get => _selectedAddonChannelType; + set { SetProperty(ref _selectedAddonChannelType, value); } + } + public Command ShowLogsCommand { get; set; } public Command TelemetryCheckCommand { get; set; } public Command CollapseToTrayCheckCommand { get; set; } @@ -68,7 +77,10 @@ namespace WowUp.WPF.ViewModels public Command SetClassicLocationCommand { get; set; } public Command SetClassicPtrLocationCommand { get; set; } public Command RescanFoldersCommand { get; set; } - + public Command AddonChannelChangeCommand { get; set; } + + public ObservableCollection AddonChannelNames { get; set; } + public OptionsViewModel( IAnalyticsService analyticsService, IWarcraftService warcraftService, @@ -86,6 +98,14 @@ namespace WowUp.WPF.ViewModels SetClassicLocationCommand = new Command(() => OnSetLocation(WowClientType.Classic)); SetClassicPtrLocationCommand = new Command(() => OnSetLocation(WowClientType.ClassicPtr)); RescanFoldersCommand = new Command(() => OnRescanFolders()); + AddonChannelChangeCommand = new Command(() => OnAddonChannelChange(SelectedAddonChannelType)); + + AddonChannelNames = new ObservableCollection + { + AddonChannelType.Stable, + AddonChannelType.Beta, + AddonChannelType.Alpha + }; LoadOptions(); } @@ -94,6 +114,7 @@ namespace WowUp.WPF.ViewModels { IsTelemetryEnabled = _analyticsService.IsTelemetryEnabled(); CollapseToTrayEnabled = _wowUpService.GetCollapseToTray(); + SelectedAddonChannelType = _wowUpService.GetDefaultAddonChannel(); WowRetailLocation = _warcraftService.GetClientLocation(WowClientType.Retail); WowRetailPtrLocation = _warcraftService.GetClientLocation(WowClientType.RetailPtr); @@ -139,5 +160,10 @@ namespace WowUp.WPF.ViewModels _warcraftService.ScanProducts(); LoadOptions(); } + + private void OnAddonChannelChange(AddonChannelType addonChannelType) + { + _wowUpService.SetDefaultAddonChannel(addonChannelType); + } } } diff --git a/WowUp.WPF/Views/OptionsView.xaml b/WowUp.WPF/Views/OptionsView.xaml index 9be7bb51..6694cfee 100644 --- a/WowUp.WPF/Views/OptionsView.xaml +++ b/WowUp.WPF/Views/OptionsView.xaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local="clr-namespace:WowUp.WPF.Views" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> @@ -108,6 +109,7 @@ + @@ -133,7 +135,23 @@ - + + + + + + + + + + + Newly installed addons will assume this release channel. + + diff --git a/WowUp.WPF/WowUp.WPF.csproj b/WowUp.WPF/WowUp.WPF.csproj index 870f7156..b0e3a12d 100644 --- a/WowUp.WPF/WowUp.WPF.csproj +++ b/WowUp.WPF/WowUp.WPF.csproj @@ -10,7 +10,7 @@ WowUp Jliddev WowUp - 1.14.1 + 1.14.2 wowup_logo_512np_RRT_icon.ico jliddev https://wowup.io @@ -46,6 +46,7 @@ +