various improvements and fixes
This commit is contained in:
jliddev
2020-07-07 11:55:38 -05:00
parent 2abd099219
commit e078f47f7f
26 changed files with 148 additions and 394 deletions

View File

@@ -143,10 +143,6 @@ namespace WowUp.WPF.AddonProviders
private CurseFile GetLatestFile(CurseSearchResult result, WowClientType clientType)
{
if (result.Name.Contains("Details"))
{
}
var clientTypeStr = GetClientTypeString(clientType);
return result.LatestFiles
@@ -198,9 +194,16 @@ namespace WowUp.WPF.AddonProviders
private string GetClientTypeString(WowClientType clientType)
{
return clientType == WowClientType.Retail
? "wow_retail"
: "wow_classic";
switch (clientType)
{
case WowClientType.Classic:
case WowClientType.ClassicPtr:
return "wow_classic";
case WowClientType.Retail:
case WowClientType.RetailPtr:
default:
return "wow_retail";
}
}

View File

@@ -24,7 +24,7 @@ namespace WowUp.WPF
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionHandler);
var logFilePath = Path.Combine(FileUtilities.AppDataPath, "logs", "wowup-logs.txt");
var logFilePath = Path.Combine(FileUtilities.AppLogsPath, "wowup-logs.txt");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
@@ -32,7 +32,7 @@ namespace WowUp.WPF
.WriteTo.File(logFilePath, rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7)
.CreateLogger();
Log.Information("Starting");
Log.Information($"Starting {GetType().Assembly.GetName().Version}");
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);

View File

@@ -1,5 +1,17 @@
{
"ChangeLogs": [
{
"Version": "1.2.4",
"Description": "More protection against weird toc files.\nImprovements to re-scan function."
},
{
"Version": "1.2.3",
"Description": "Add some extra logging and error catching.\nFix some issues searching curse for addons for PTR clients."
},
{
"Version": "1.2.2",
"Description": "Add Show Log Files button.\nAdd in recurring call to check for app updates every 10 minutes.\nBetter wow folder selection validation."
},
{
"Version": "1.2.1",
"Description": "Add correct task bar icon."

View File

@@ -196,6 +196,7 @@
HorizontalAlignment="Center">
<TextBlock Text="Welcome" FontSize="20" HorizontalAlignment="Center" />
<TextBlock Text="Please select your World of Warcraft folder" FontSize="14" />
<TextBlock Text="Example: C:\Program Files (x86)\World of Warcraft" Foreground="{StaticResource White2}" FontSize="12" />
<Button x:Name="SelectWowButton" Click="SelectWowButton_Click" Margin="0, 10" Style="{StaticResource purpleButton}">Select</Button>
</StackPanel>
<TabControl x:Name="Tabs"

View File

@@ -48,9 +48,25 @@ namespace WowUp.WPF.Repositories
return true;
}
public bool DeleteItem(string id)
public bool DeleteItem(Addon addon)
{
throw new NotImplementedException();
lock (_collisionLock)
{
_database.Delete(addon);
}
return true;
}
public bool DeleteItems(IEnumerable<Addon> addons)
{
lock (_collisionLock)
{
foreach(var addon in addons)
{
_database.Delete(addon);
}
}
return true;
}
public IEnumerable<Addon> Query(Func<TableQuery<Addon>, TableQuery<Addon>> action)

View File

@@ -31,7 +31,7 @@ namespace WowUp.WPF.Repositories.Base
{
_database.Execute("PRAGMA journal_mode = 'wal'");
}
catch (Exception ex)
catch (Exception)
{
// eat
}

View File

@@ -10,7 +10,8 @@ namespace WowUp.WPF.Repositories.Contracts
bool AddItems(IEnumerable<T> item);
bool SaveItems(IEnumerable<T> items);
bool UpdateItem(T item);
bool DeleteItem(string id);
bool DeleteItem(T item);
bool DeleteItems(IEnumerable<T> addons);
IEnumerable<T> Query(Func<TableQuery<T>, TableQuery<T>> action);
T Query(Func<TableQuery<T>, T> action);
}

View File

@@ -53,7 +53,7 @@ namespace WowUp.WPF.Repositories
return true;
}
public bool DeleteItem(string id)
public bool DeleteItem(Preference preference)
{
throw new NotImplementedException();
}
@@ -114,5 +114,10 @@ namespace WowUp.WPF.Repositories
return true;
}
public bool DeleteItems(IEnumerable<Preference> addons)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,152 +0,0 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using WowUp.WPF.Entities;
using WowUp.WPF.Repositories.Contracts;
using WowUp.WPF.Services.Base;
using WowUp.WPF.Utilities;
namespace WowUp.WPF.Services
{
public class AddonDataStore : SingletonService<AddonDataStore>, IDataStore<Addon>
{
private static object _collisionLock = new object();
private SQLiteConnection _database;
public ObservableCollection<Addon> Addons { get; set; }
public AddonDataStore()
{
_database = DbConnection();
_database.CreateTable<Addon>();
EnableWriteAheadLogging();
Addons = new ObservableCollection<Addon>(_database.Table<Addon>());
}
public bool AddItem(Addon item)
{
lock (_collisionLock)
{
item.UpdatedAt = DateTime.UtcNow;
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
return true;
}
public bool UpdateItem(Addon item)
{
lock (_collisionLock)
{
item.UpdatedAt = DateTime.UtcNow;
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
return true;
}
public bool DeleteItem(string id)
{
throw new NotImplementedException();
}
public IEnumerable<Addon> Query(Func<TableQuery<Addon>, TableQuery<Addon>> action)
{
lock (_collisionLock)
{
var query = action.Invoke(_database.Table<Addon>());
return query.AsEnumerable();
}
}
public Addon Query(Func<TableQuery<Addon>, Addon> action)
{
lock (_collisionLock)
{
return action.Invoke(_database.Table<Addon>());
}
}
public bool AddItems(IEnumerable<Addon> items)
{
lock (_collisionLock)
{
foreach (var item in items)
{
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
}
return true;
}
public bool SaveItems(IEnumerable<Addon> items)
{
lock (_collisionLock)
{
foreach (var item in items)
{
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
}
return true;
}
private void EnableWriteAheadLogging()
{
// Enable write-ahead logging
try
{
_database.Execute("PRAGMA journal_mode = 'wal'");
}
catch (Exception ex)
{
// eat
}
}
private SQLiteConnection DbConnection()
{
var dbName = "WowUp.db3";
var path = Path.Combine(FileUtilities.AppDataPath, dbName);
return new SQLiteConnection(path);
}
}
}

View File

@@ -9,7 +9,6 @@ using WowUp.WPF.AddonProviders.Contracts;
using WowUp.WPF.Entities;
using WowUp.WPF.Models;
using WowUp.WPF.Repositories.Contracts;
using WowUp.WPF.Services.Base;
using WowUp.WPF.Services.Contracts;
using WowUp.WPF.Utilities;
@@ -59,21 +58,24 @@ namespace WowUp.WPF.Services
public async Task<List<Addon>> GetAddons(WowClientType clientType, bool rescan = false)
{
var addons = GetAllStoredAddons(clientType);
if (!addons.Any())
if (rescan || !addons.Any())
{
RemoveAddons(clientType);
addons = await GetLocalAddons(clientType);
SaveAddons(addons);
}
else if (rescan)
{
addons = await RescanAddons(addons, clientType);
}
await SyncAddons(clientType, addons);
return addons;
}
private void RemoveAddons(WowClientType clientType)
{
var addons = GetAllStoredAddons(clientType);
_addonRepository.DeleteItems(addons);
}
private async Task SyncAddons(WowClientType clientType, IEnumerable<Addon> addons)
{
var addonIds = addons.Select(addon => addon.CurseAddonId);
@@ -120,7 +122,7 @@ namespace WowUp.WPF.Services
{
updateAction?.Invoke(AddonInstallState.BackingUp, 0.50m);
var backupZipFilePath = Path.Combine(BackupPath, $"{addon.Name}-{addon.InstalledVersion}.zip");
await _downloadService.ZipFile(downloadedFilePath, backupZipFilePath);
//await _downloadService.ZipFile(downloadedFilePath, backupZipFilePath);
}
updateAction?.Invoke(AddonInstallState.Installing, 75m);
@@ -227,18 +229,33 @@ namespace WowUp.WPF.Services
public async Task<List<Addon>> MapAll(IEnumerable<Addon> addons, WowClientType clientType)
{
if(addons == null)
{
Log.Warning("Addon list was null");
return new List<Addon>();
}
foreach (var addon in addons)
{
var searchResults = await Search(addon.Name, addon.FolderName, clientType);
var firstResult = searchResults.FirstOrDefault();
if (firstResult == null)
{
return null;
}
Log.Debug($"Addon {addon.FolderName}");
addon.LatestVersion = firstResult.Version;
addon.GameVersion = firstResult.GameVersion;
addon.Author = firstResult.Author;
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();
@@ -250,13 +267,20 @@ namespace WowUp.WPF.Services
foreach (var addonFolder in addonFolders)
{
var addon = await Map(addonFolder.Toc.Title, addonFolder.Name, clientType);
if (addon == null)
try
{
continue;
}
var addon = await Map(addonFolder.Toc.Title, addonFolder.Name, clientType);
if (addon == null)
{
continue;
}
results[addon.Name] = addon;
results[addon.Name] = addon;
}
catch(Exception ex)
{
Log.Error(ex, $"Failed to map addon folder {addonFolder.Name}");
}
}
return results.Values

View File

@@ -1,47 +0,0 @@
using SQLite;
using System;
using System.Collections.ObjectModel;
using System.IO;
using WowUp.WPF.Utilities;
namespace WowUp.WPF.Services.Base
{
public class BaseDataStore<T>
where T : new()
{
protected static object _collisionLock = new object();
protected SQLiteConnection _database;
protected ObservableCollection<T> _entities;
public BaseDataStore()
{
_database = DbConnection();
_database.CreateTable<T>();
EnableWriteAheadLogging();
_entities = new ObservableCollection<T>(_database.Table<T>());
}
private void EnableWriteAheadLogging()
{
// Enable write-ahead logging
try
{
_database.Execute("PRAGMA journal_mode = 'wal'");
}
catch (Exception ex)
{
// eat
}
}
private SQLiteConnection DbConnection()
{
var dbName = "WowUp.db3";
var path = Path.Combine(FileUtilities.AppDataPath, dbName);
return new SQLiteConnection(path);
}
}
}

View File

@@ -1,11 +0,0 @@
using System;
namespace WowUp.WPF.Services.Base
{
public class SingletonService<T> where T : new()
{
private static readonly Lazy<T> lazy = new Lazy<T>(() => new T());
public static T Instance { get { return lazy.Value; } }
}
}

View File

@@ -1,24 +0,0 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace WowUp.WPF.Services.Contracts
{
public interface IDataStore<T>
{
bool AddItem(T item);
bool AddItems(IEnumerable<T> item);
bool UpdateItem(T item);
bool DeleteItem(string id);
IEnumerable<T> Query(Func<TableQuery<T>, TableQuery<T>> action);
T Query(Func<TableQuery<T>, T> action);
Task<bool> AddItemAsync(T item);
Task<bool> UpdateItemAsync(T item);
Task<bool> DeleteItemAsync(string id);
Task<T> GetItemAsync(string id);
Task<IEnumerable<T>> GetItemsAsync(bool forceRefresh = false);
}
}

View File

@@ -9,6 +9,7 @@ namespace WowUp.WPF.Services.Contracts
Task<IList<string>> GetWowClientNames();
Task<IList<WowClientType>> GetWowClients();
bool ValidateWowFolder(string wowFolder);
Task<string> GetWowFolderPath();
Task<bool> SetWowFolderPath(string folderPath);
Task<string> GetRetailFolderPath();

View File

@@ -6,6 +6,8 @@ namespace WowUp.WPF.Services.Contracts
{
public interface IWowUpService
{
void ShowLogsFolder();
Version CurrentVersion { get; }
string CurrentVersionString { get; }

View File

@@ -3,7 +3,6 @@ using System;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
using WowUp.WPF.Services.Base;
using WowUp.WPF.Services.Contracts;
namespace WowUp.WPF.Services

View File

@@ -1,113 +0,0 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using WowUp.WPF.Entities;
using WowUp.WPF.Repositories.Contracts;
using WowUp.WPF.Services.Base;
namespace WowUp.WPF.Services
{
public class PreferenceDataStore : BaseDataStore<Preference>, IDataStore<Preference>
{
public bool AddItem(Preference item)
{
lock (_collisionLock)
{
item.UpdatedAt = DateTime.UtcNow;
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
return true;
}
public bool UpdateItem(Preference item)
{
lock (_collisionLock)
{
item.UpdatedAt = DateTime.UtcNow;
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
return true;
}
public bool DeleteItem(string id)
{
throw new NotImplementedException();
}
public IEnumerable<Preference> Query(Func<TableQuery<Preference>, TableQuery<Preference>> action)
{
lock (_collisionLock)
{
var query = action.Invoke(_database.Table<Preference>());
return query.AsEnumerable();
}
}
public Preference Query(Func<TableQuery<Preference>, Preference> action)
{
lock (_collisionLock)
{
return action.Invoke(_database.Table<Preference>());
}
}
public bool AddItems(IEnumerable<Preference> items)
{
lock (_collisionLock)
{
foreach (var item in items)
{
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
}
return true;
}
public bool SaveItems(IEnumerable<Preference> items)
{
lock (_collisionLock)
{
foreach (var item in items)
{
if (item.Id != 0)
{
_database.Update(item);
}
else
{
_database.Insert(item);
}
}
}
return true;
}
}
}

View File

@@ -10,6 +10,7 @@ using WowUp.WPF.Repositories.Contracts;
using WowUp.WPF.Services.Contracts;
using WowUp.WPF.Utilities;
using WowUp.WPF.Extensions;
using Serilog;
namespace WowUp.WPF.Services
{
@@ -106,6 +107,8 @@ namespace WowUp.WPF.Services
public Task<string> GetWowFolderPath()
{
var preference = GetWowLocationPreference();
Log.Debug($"Wow Preference {preference?.Value}");
return Task.FromResult(preference?.Value);
}
@@ -134,9 +137,12 @@ namespace WowUp.WPF.Services
public async Task<IEnumerable<AddonFolder>> ListAddons(WowClientType clientType)
{
var addonsPath = await GetAddonFolderPath(clientType);
Log.Debug($"AddonsPath {addonsPath}");
var addons = new List<AddonFolder>();
var addonDirectories = Directory.GetDirectories(addonsPath);
Log.Debug($"addonDirectories {addonDirectories.Length}");
foreach (var directory in addonDirectories)
{
var directoryInfo = new DirectoryInfo(directory);
@@ -152,14 +158,18 @@ namespace WowUp.WPF.Services
return _preferenceRepository.FindByKey(WowLocationPreferenceKey);
}
private bool ValidateWowFolder(string wowFolder)
public bool ValidateWowFolder(string wowFolder)
{
try
{
var directories = Directory.GetDirectories(wowFolder);
return directories.Any(dir => FolderNames.Any(fn => dir.Contains(fn)));
return directories.Any(dir =>
{
var dirName = Path.GetFileName(dir);
return FolderNames.Any(fn => dirName.Contains(fn));
});
}
catch(Exception ex)
catch(Exception)
{
return false;
}

View File

@@ -4,8 +4,10 @@ using Serilog;
using System;
using System.Linq;
using System.Threading.Tasks;
using WowUp.WPF.Extensions;
using WowUp.WPF.Models;
using WowUp.WPF.Services.Contracts;
using WowUp.WPF.Utilities;
namespace WowUp.WPF.Services
{
@@ -27,6 +29,11 @@ namespace WowUp.WPF.Services
_cache = memoryCache;
}
public void ShowLogsFolder()
{
FileUtilities.AppLogsPath.OpenUrlInBrowser();
}
public async Task<bool> IsUpdateAvailable()
{
var latestVersionStr = await GetLatestVersion();
@@ -55,7 +62,6 @@ namespace WowUp.WPF.Services
return string.Empty;
}
return changeLogFile.ChangeLogs?.FirstOrDefault()?.Version ?? string.Empty;
}

View File

@@ -10,6 +10,7 @@ namespace WowUp.WPF.Utilities
.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
public static readonly string AppDataPath = Path.Combine(LocalAppDataPath, "WowUp");
public static readonly string AppLogsPath = Path.Combine(AppDataPath, "Logs");
static FileUtilities()
{

View File

@@ -143,7 +143,6 @@ namespace WowUp.WPF.ViewModels
catch (Exception ex)
{
Log.Error(ex, "LoadItems");
Debug.WriteLine(ex);
}
finally
{

View File

@@ -19,6 +19,8 @@ namespace WowUp.WPF.ViewModels
private readonly IWarcraftService _warcraftService;
private readonly IWowUpService _wowUpService;
private System.Threading.Timer _timer;
public Command SelectWowCommand { get; set; }
public Command DownloadLatestVersionCommand { get; set; }
@@ -80,6 +82,8 @@ namespace WowUp.WPF.ViewModels
TabItems = new ObservableCollection<TabItem>();
_timer = new System.Threading.Timer(CheckVersion, null, TimeSpan.Zero, TimeSpan.FromMinutes(10));
InitializeView();
}
@@ -99,8 +103,6 @@ namespace WowUp.WPF.ViewModels
private async void InitializeView()
{
CheckVersion();
var hasWowLocation = await HasWarcraftLocation();
ShowWowSelection = !hasWowLocation;
@@ -112,7 +114,7 @@ namespace WowUp.WPF.ViewModels
}
}
private async void CheckVersion()
private async void CheckVersion(object state)
{
IsUpdateAvailable = await _wowUpService.IsUpdateAvailable();
}
@@ -153,7 +155,7 @@ namespace WowUp.WPF.ViewModels
private async Task<bool> HasWarcraftLocation()
{
var wowFolder = await _warcraftService.GetWowFolderPath();
return !string.IsNullOrEmpty(wowFolder);
return _warcraftService.ValidateWowFolder(wowFolder) && !string.IsNullOrEmpty(wowFolder);
}
private void DownloadLatestVersion()

View File

@@ -11,6 +11,7 @@ namespace WowUp.WPF.ViewModels
public class OptionsViewModel : BaseViewModel
{
private readonly IWarcraftService _warcraftService;
private readonly IWowUpService _wowUpService;
private string _wowLocation;
public string WowLocation
@@ -19,10 +20,16 @@ namespace WowUp.WPF.ViewModels
set { SetProperty(ref _wowLocation, value); }
}
public Command ShowLogsCommand { get; set; }
public OptionsViewModel(
IWarcraftService warcraftService)
IWarcraftService warcraftService,
IWowUpService wowUpService)
{
_warcraftService = warcraftService;
_wowUpService = wowUpService;
ShowLogsCommand = new Command(() => ShowLogsFolder());
LoadOptions();
}
@@ -32,6 +39,11 @@ namespace WowUp.WPF.ViewModels
WowLocation = await _warcraftService.GetWowFolderPath();
}
private void ShowLogsFolder()
{
_wowUpService.ShowLogsFolder();
}
public async void SetWowLocation()
{
var selectedPath = DialogUtilities.SelectFolder();

View File

@@ -24,6 +24,8 @@
<TextBlock FontSize="15" Text="World of Warcraft install location" />
<TextBox Margin="0, 10" Text="{Binding WowLocation}" IsEnabled="False" FontSize="14"/>
<Button x:Name="SelectLocationButton" Click="SelectLocationButton_Click" Style="{StaticResource purpleButton}">Select Location</Button>
<TextBlock FontSize="15" Text="Log files" Margin="0 10 0 5" />
<Button x:Name="ShowLogsButton" Command="{Binding ShowLogsCommand}" Style="{StaticResource purpleButton}">Show Log Files</Button>
</StackPanel>
</Border>
</Grid>

View File

@@ -21,5 +21,10 @@ namespace WowUp.WPF.Views
{
_viewModel.SetWowLocation();
}
private void ShowLogsButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
}
}
}

View File

@@ -10,7 +10,7 @@
<PackageId>WowUp</PackageId>
<Authors>Jliddev</Authors>
<Product>WowUp</Product>
<Version>1.2.1</Version>
<Version>1.2.4</Version>
<ApplicationIcon>wowup_logo_512np_RRT_icon.ico</ApplicationIcon>
</PropertyGroup>