From 87ecb8ef016b15717befdc2f3f25f6764d73afa7 Mon Sep 17 00:00:00 2001 From: RattleSN4K3 Date: Thu, 15 May 2025 03:04:48 +0200 Subject: [PATCH] Store installed flag in local library, pre-select addons on Modify/Install dialog --- .../DownloadQueueRedistributable.cs | 1 + .../IInstallQueueItem.cs | 1 + .../InstallQueueGame.cs | 1 + .../InstallService.cs | 54 ++++++++++++++++--- .../LibraryService.cs | 1 + .../UI/Components/InstallDialog.razor | 10 ++-- 6 files changed, 56 insertions(+), 12 deletions(-) diff --git a/LANCommander.Launcher.Models/DownloadQueueRedistributable.cs b/LANCommander.Launcher.Models/DownloadQueueRedistributable.cs index fe72e3fe..f9b3981f 100644 --- a/LANCommander.Launcher.Models/DownloadQueueRedistributable.cs +++ b/LANCommander.Launcher.Models/DownloadQueueRedistributable.cs @@ -11,6 +11,7 @@ namespace LANCommander.Launcher.Models { public Guid Id { get; set; } public Guid[] AddonIds { get; set; } + public Dictionary AddonVersions { get; set; } public string Title { get; set; } public string Version { get; set; } public string InstallDirectory { get; set; } diff --git a/LANCommander.Launcher.Models/IInstallQueueItem.cs b/LANCommander.Launcher.Models/IInstallQueueItem.cs index 6c82801a..5001a769 100644 --- a/LANCommander.Launcher.Models/IInstallQueueItem.cs +++ b/LANCommander.Launcher.Models/IInstallQueueItem.cs @@ -11,6 +11,7 @@ namespace LANCommander.Launcher.Models { Guid Id { get; set; } Guid[] AddonIds { get; set; } + Dictionary AddonVersions { get; set; } string Title { get; set; } string Version { get; set; } string InstallDirectory { get; set; } diff --git a/LANCommander.Launcher.Models/InstallQueueGame.cs b/LANCommander.Launcher.Models/InstallQueueGame.cs index 17a5cc1a..065c2513 100644 --- a/LANCommander.Launcher.Models/InstallQueueGame.cs +++ b/LANCommander.Launcher.Models/InstallQueueGame.cs @@ -11,6 +11,7 @@ namespace LANCommander.Launcher.Models { public Guid Id { get; set; } public Guid[] AddonIds { get; set; } + public Dictionary AddonVersions { get; set; } public string Title { get; set; } public string Version { get; set; } public string InstallDirectory { get; set; } diff --git a/LANCommander.Launcher.Services/InstallService.cs b/LANCommander.Launcher.Services/InstallService.cs index 1de53ec4..24a41394 100644 --- a/LANCommander.Launcher.Services/InstallService.cs +++ b/LANCommander.Launcher.Services/InstallService.cs @@ -53,7 +53,7 @@ namespace LANCommander.Launcher.Services Queue.CollectionChanged += (sender, e) => { OnQueueChanged?.Invoke(); - }; + }; Client.Games.OnInstallProgressUpdate += (e) => { @@ -79,7 +79,15 @@ namespace LANCommander.Launcher.Services OnQueueChanged?.Invoke(); } - public async Task Add(Game game, string installDirectory = "", Guid[] addonIds = null) + [Obsolete("Use Add(Game, string, Game[]) instead.")] + public async Task AddObsolete(Game game, string installDirectory = "", Guid[]? addonIds = null) + { + var addons = addonIds != null ? await Client.Games.GetAddonsAsync(game.Id) : []; + var selectedAddons = addons?.Where(x => addons.Contains(x)).ToArray(); + await Add(game, installDirectory, selectedAddons); + } + + public async Task Add(Game game, string installDirectory = "", SDK.Models.Game[]? addons = null) { var gameInfo = await Client.Games.GetAsync(game.Id); @@ -118,8 +126,14 @@ namespace LANCommander.Launcher.Services queueItem.InstallDirectory = installDirectory; - if (addonIds != null && addonIds.Length > 0) + if (addons != null && addons.Length > 0) + { + var versions = addons.ToLookup(addon => addon.Id, x => x.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault()?.Version); + var addonIds = addons.Select(x => x.Id).ToArray() ?? []; + queueItem.AddonIds = addonIds; + queueItem.AddonVersions = addonIds.ToDictionary(x => x, y => versions[y]?.FirstOrDefault()); + } if (Queue.Any(i => i.State)) Queue.Add(queueItem); @@ -201,7 +215,16 @@ namespace LANCommander.Launcher.Services { // Probably doing a modification of some sort if (localGame.InstallDirectory.StartsWith(currentItem.InstallDirectory)) + { await Client.Games.InstallAddonsAsync(localGame.InstallDirectory, localGame.Id, currentItem.AddonIds); + + UpdateGameState(currentItem, localGame, localGame.InstallDirectory); + await GameService.UpdateAsync(localGame); + + currentItem.Status = InstallStatus.Complete; + OnQueueChanged?.Invoke(); + OnInstallComplete?.Invoke(localGame); + } else { await Move(currentItem, localGame, remoteGame); @@ -230,11 +253,7 @@ namespace LANCommander.Launcher.Services try { installDirectory = await Client.Games.InstallAsync(remoteGame.Id, currentItem.InstallDirectory, currentItem.AddonIds); - - localGame.InstallDirectory = installDirectory; - localGame.Installed = true; - localGame.InstalledVersion = currentItem.Version; - localGame.InstalledOn = DateTime.Now; + UpdateGameState(currentItem, localGame, installDirectory); } catch (InstallCanceledException ex) { @@ -314,6 +333,25 @@ namespace LANCommander.Launcher.Services await Next(); } + private static void UpdateGameState(IInstallQueueItem currentItem, Game localGame, string installDirectory) + { + localGame.InstallDirectory = installDirectory; + localGame.Installed = true; + localGame.InstalledVersion = currentItem.Version; + localGame.InstalledOn ??= DateTime.Now; + + foreach (var addonId in (currentItem.AddonIds ?? [])) + { + var localAddon = localGame.DependentGames.FirstOrDefault(d => d.Id == addonId); + if (localAddon == null) continue; + + localAddon.InstallDirectory = installDirectory; + localAddon.Installed = true; + localAddon.InstalledVersion = currentItem.AddonVersions.TryGetValue(localAddon.Id, out var addonVersion) ? addonVersion : null; + localAddon.InstalledOn ??= DateTime.Now; + } + } + public async Task Move(IInstallQueueItem currentItem, Game localGame, SDK.Models.Game remoteGame) { using (var operation = Logger.BeginOperation("Moving game {GameTitle} ({GameId}) to {Destination}", localGame.Title, localGame.Id, currentItem.InstallDirectory)) diff --git a/LANCommander.Launcher.Services/LibraryService.cs b/LANCommander.Launcher.Services/LibraryService.cs index b1abcd62..a3fb0e8c 100644 --- a/LANCommander.Launcher.Services/LibraryService.cs +++ b/LANCommander.Launcher.Services/LibraryService.cs @@ -217,6 +217,7 @@ namespace LANCommander.Launcher.Services .Include(g => g.Platforms) .Include(g => g.Media) .Include(g => g.MultiplayerModes) + .Include(g => g.DependentGames) .FirstOrDefaultAsync(g => g.Id == key); return new ListItem(game); diff --git a/LANCommander.Launcher/UI/Components/InstallDialog.razor b/LANCommander.Launcher/UI/Components/InstallDialog.razor index a7542614..1d6abbd0 100644 --- a/LANCommander.Launcher/UI/Components/InstallDialog.razor +++ b/LANCommander.Launcher/UI/Components/InstallDialog.razor @@ -59,11 +59,10 @@ string SelectedDirectory = ""; - List Addons = new(); - SDK.Models.Game RemoteGame; Data.Models.Game Game; + List Addons = new(); IEnumerable SelectedAddons = new List(); enum InstallOperation @@ -77,7 +76,7 @@ protected override async Task OnInitializedAsync() { Game = Options.DataItem as Game; - + if (Game.Installed) SelectedDirectory = Settings.Games.InstallDirectories.FirstOrDefault(d => Game.InstallDirectory.StartsWith(d)); @@ -86,6 +85,9 @@ RemoteGame = await Client.Games.GetAsync(Options.Key); Addons = (await Client.Games.GetAddonsAsync(Options.Key)).OrderByTitle(g => g.SortTitle ?? g.Title).ToList(); + + var localAddons = Game?.DependentGames.Where(g => g.Installed).Select(addon => addon.Id).ToArray() ?? []; + SelectedAddons = Addons?.Where(addon => localAddons.Contains(addon.Id)).ToList() ?? []; } async Task Close() @@ -97,7 +99,7 @@ { var game = Options.DataItem as Game; - InstallService.Add(game, SelectedDirectory, SelectedAddons.Select(a => a.Id).ToArray()); + InstallService.Add(game, SelectedDirectory, SelectedAddons.ToArray()); await CloseFeedbackAsync(); }