Skip to content

Commit c167d0e

Browse files
Merge pull request #37 from KrystianLesniak/develop
Release: 1.6.0
2 parents fa2d514 + b1b430d commit c167d0e

File tree

15 files changed

+214
-91
lines changed

15 files changed

+214
-91
lines changed

src/GamesLauncher.Common/Settings/HiddenGames.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class HiddenGames
1010
Platform = "Steam",
1111
Title = "Steamworks Common Redistributables"
1212
}
13-
};
13+
};
1414

1515
public void Hide(string title, string platform, string internalGameId)
1616
{

src/GamesLauncher.Platforms/Game.cs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,47 @@ namespace GamesLauncher.Platforms
55
{
66
public class Game
77
{
8-
internal Game(string Title,
9-
Func<ActionContext, ValueTask<bool>> RunTask,
10-
string? IconPath,
11-
IconDelegate? IconDelegate,
12-
string Platform)
8+
internal Game(string title,
9+
Func<ActionContext, ValueTask<bool>> runTask,
10+
string? iconPath,
11+
IconDelegate? iconDelegate,
12+
string platform,
13+
UninstallAction? uninstallAction = null)
1314
{
14-
this.Title = Title;
15-
this.RunTask = RunTask;
16-
this.IconPath = IconPath;
17-
this.IconDelegate = IconDelegate;
18-
this.Platform = Platform;
15+
Title = title;
16+
RunTask = runTask;
17+
IconPath = iconPath;
18+
IconDelegate = iconDelegate;
19+
Platform = platform;
20+
UninstallAction = uninstallAction;
1921
}
2022

2123
public string Title { get; }
2224
public Func<ActionContext, ValueTask<bool>> RunTask { get; }
25+
public UninstallAction? UninstallAction { get; }
2326
public string? IconPath { get; }
2427
public IconDelegate? IconDelegate { get; }
2528
public string Platform { get; }
2629
public string InternalGameId => $"{Platform}_{Title}";
2730

2831
}
32+
33+
public class UninstallAction
34+
{
35+
public string Title { get; } = "Uninstall";
36+
37+
public Func<Task> UninstallTask { get; }
38+
39+
internal UninstallAction(Func<Task> uninstallTask)
40+
{
41+
UninstallTask = uninstallTask;
42+
}
43+
44+
internal UninstallAction(Func<Task> uninstallTask, string title)
45+
{
46+
Title = title;
47+
UninstallTask = uninstallTask;
48+
}
49+
50+
}
2951
}

src/GamesLauncher.Platforms/GamesLauncher.Platforms.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>net7.0-windows</TargetFramework>
@@ -20,7 +20,7 @@
2020
<PackageReference Include="GameFinder.StoreHandlers.Steam" Version="4.0.0" />
2121
<PackageReference Include="GameFinder.StoreHandlers.Xbox" Version="4.0.0" />
2222
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.5" />
23-
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.12" />
23+
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.13" />
2424
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
2525
</ItemGroup>
2626

src/GamesLauncher.Platforms/PlatformsManager.cs

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
using GamesLauncher.Platforms.SyncEngines.Amazon;
55
using GamesLauncher.Platforms.SyncEngines.Epic;
66
using GamesLauncher.Platforms.SyncEngines.Steam;
7-
using System.Collections.Concurrent;
7+
using System.Diagnostics;
88

99
namespace GamesLauncher.Platforms
1010
{
1111
public class PlatformsManager
1212
{
13-
private IEnumerable<Game> Games = Array.Empty<Game>();
13+
public IEnumerable<Game> AllSynchronizedGames => Engines.SelectMany(x => x.SynchronizedGames);
14+
15+
private IEnumerable<ISyncEngine> Engines { get; set; } = Array.Empty<ISyncEngine>();
1416

1517
private readonly IPublicAPI publicApi;
1618

@@ -21,18 +23,25 @@ public PlatformsManager(IPublicAPI publicApi)
2123

2224
public async Task SynchronizeGames(MainSettings settings)
2325
{
24-
var engines = InitializeEngines(settings);
25-
Games = await SynchronizeLibraries(engines);
26-
}
26+
#if DEBUG
27+
var stopwatch = Stopwatch.StartNew();
28+
#endif
2729

28-
public IEnumerable<Game> GetSynchronizedGames()
29-
{
30-
return Games;
30+
Engines = InitializeEngines(settings);
31+
await Parallel.ForEachAsync(Engines, async (engine, ct) =>
32+
{
33+
await engine.SynchronizeGames();
34+
});
35+
36+
#if DEBUG
37+
stopwatch.Stop();
38+
publicApi.LogInfo(nameof(PlatformsManager), $"GamesLauncher: Games synchronization time: {stopwatch.Elapsed}");
39+
#endif
3140
}
3241

3342
public Game? GetGame(string title, string platform)
3443
{
35-
return Games.FirstOrDefault(x=> x.Title == title && x.Platform == platform);
44+
return AllSynchronizedGames.FirstOrDefault(x => x.Title == title && x.Platform == platform);
3645
}
3746

3847
private IEnumerable<ISyncEngine> InitializeEngines(MainSettings settings)
@@ -55,20 +64,5 @@ private IEnumerable<ISyncEngine> InitializeEngines(MainSettings settings)
5564

5665
return engines;
5766
}
58-
59-
private static async Task<IEnumerable<Game>> SynchronizeLibraries(IEnumerable<ISyncEngine> engines)
60-
{
61-
var games = new ConcurrentBag<Game>();
62-
63-
await Parallel.ForEachAsync(engines, async (engine, ct) =>
64-
{
65-
await foreach (var game in engine.GetGames())
66-
{
67-
games.Add(game);
68-
};
69-
});
70-
71-
return games;
72-
}
7367
}
7468
}

src/GamesLauncher.Platforms/SyncEngines/Amazon/AmazonSyncEngine.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using Flow.Launcher.Plugin;
22
using GamesLauncher.Platforms.SyncEngines.Amazon.Readers;
3+
using System.Collections.Concurrent;
34

45
namespace GamesLauncher.Platforms.SyncEngines.Amazon
56
{
67
internal class AmazonSyncEngine : ISyncEngine
78
{
89
public string PlatformName => "Amazon Games";
10+
public IEnumerable<Game> SynchronizedGames { get; private set; } = Array.Empty<Game>();
11+
912

1013
private readonly IPublicAPI publicApi;
1114

@@ -14,21 +17,25 @@ public AmazonSyncEngine(IPublicAPI publicApi)
1417
this.publicApi = publicApi;
1518
}
1619

17-
public async IAsyncEnumerable<Game> GetGames()
20+
public async Task SynchronizeGames()
1821
{
1922
await using var installInfoReader = new InstallInfoReader();
2023
await using var productDetailsReader = new ProductDetailsReader();
2124

25+
var syncedGames = new ConcurrentBag<Game>();
26+
2227
await foreach (var gameInstallInfo in installInfoReader.GetInstalledGamesId())
2328
{
24-
yield return new Game(
25-
Title: gameInstallInfo.Title,
26-
RunTask: GetGameRunTask(gameInstallInfo.Id),
27-
IconPath: await productDetailsReader.GetIconUrlById(gameInstallInfo.Id),
28-
IconDelegate: null,
29-
Platform: PlatformName
30-
);
29+
syncedGames.Add(new Game(
30+
title: gameInstallInfo.Title,
31+
runTask: GetGameRunTask(gameInstallInfo.Id),
32+
iconPath: await productDetailsReader.GetIconUrlById(gameInstallInfo.Id),
33+
iconDelegate: null,
34+
platform: PlatformName
35+
));
3136
}
37+
38+
SynchronizedGames = syncedGames;
3239
}
3340

3441

src/GamesLauncher.Platforms/SyncEngines/Amazon/Readers/ProductDetailsReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Microsoft.Data.Sqlite;
2-
using Newtonsoft.Json.Linq;
32
using Newtonsoft.Json;
3+
using Newtonsoft.Json.Linq;
44
using System.Data;
55
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
66

src/GamesLauncher.Platforms/SyncEngines/Epic/EpicSyncEngine.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,39 @@ namespace GamesLauncher.Platforms.SyncEngines.Epic
99
{
1010
internal class EpicSyncEngine : ISyncEngine
1111
{
12-
private readonly IPublicAPI publicApi;
13-
1412
public string PlatformName => "Epic Games Launcher";
13+
public IEnumerable<Game> SynchronizedGames { get; private set; } = Array.Empty<Game>();
14+
15+
private readonly IPublicAPI publicApi;
1516

1617
public EpicSyncEngine(IPublicAPI publicApi)
1718
{
1819
this.publicApi = publicApi;
1920
}
2021

21-
public async IAsyncEnumerable<Game> GetGames()
22+
public async Task SynchronizeGames()
2223
{
2324
var epicGames = await GetEpicGamesFromMetadata();
2425

26+
var syncedGames = new List<Game>();
27+
2528
foreach (var epicGame in epicGames)
2629
{
27-
28-
yield return new Game(
29-
Title: epicGame.DisplayName,
30-
RunTask: PrepareRunTask(epicGame.CatalogNamespace, epicGame.CatalogItemId, epicGame.AppName),
31-
IconPath: PrepareIconPath(epicGame),
32-
Platform: PlatformName,
33-
IconDelegate: null
34-
);
30+
syncedGames.Add(new Game(
31+
title: epicGame.DisplayName,
32+
runTask: PrepareRunTask(epicGame.CatalogNamespace, epicGame.CatalogItemId, epicGame.AppName),
33+
iconPath: PrepareIconPath(epicGame),
34+
platform: PlatformName,
35+
iconDelegate: null
36+
));
3537
}
38+
39+
SynchronizedGames = syncedGames;
3640
}
3741

3842
private static async Task<IEnumerable<EpicGame>> GetEpicGamesFromMetadata()
3943
{
40-
var metadataDir = (string?)Registry.GetValue(EpicGamesConsts.RegKeyPath, EpicGamesConsts.RegKeyValueName, string.Empty);
44+
var metadataDir = Registry.GetValue(EpicGamesConsts.RegKeyPath, EpicGamesConsts.RegKeyValueName, string.Empty) as string;
4145

4246
if (string.IsNullOrEmpty(metadataDir))
4347
return Array.Empty<EpicGame>();

src/GamesLauncher.Platforms/SyncEngines/ISyncEngine.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
internal interface ISyncEngine
44
{
55
string PlatformName { get; }
6-
IAsyncEnumerable<Game> GetGames();
6+
IEnumerable<Game> SynchronizedGames { get; }
7+
Task SynchronizeGames();
78
}

src/GamesLauncher.Platforms/SyncEngines/ShortcutsSyncEngine.cs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
namespace GamesLauncher.Platforms.SyncEngines
55
{
66
public class ShortcutsSyncEngine : ISyncEngine
7-
87
{
98
public string PlatformName => "Shortcut";
9+
public IEnumerable<Game> SynchronizedGames { get; private set; } = Array.Empty<Game>();
1010

1111
private readonly IPublicAPI publicApi;
1212
private readonly DirectoryInfo shortcutsDirectory;
@@ -17,23 +17,30 @@ public ShortcutsSyncEngine(IPublicAPI publicApi)
1717
shortcutsDirectory = Directory.CreateDirectory(Paths.CustomShortcutsDirectory);
1818
}
1919

20-
public async IAsyncEnumerable<Game> GetGames()
20+
public async Task SynchronizeGames()
2121
{
2222
string[] shortcutExtensions = { "*.url", "*.lnk" };
23+
var syncedGames = new List<Game>();
2324

2425
foreach (var shortcutExtension in shortcutExtensions)
2526
{
2627
foreach (var shortcut in shortcutsDirectory.EnumerateFiles(shortcutExtension, SearchOption.AllDirectories))
2728
{
28-
yield return new Game(
29-
Title: Path.GetFileNameWithoutExtension(shortcut.FullName),
30-
RunTask: GetGameRunTask(shortcut.FullName),
31-
IconPath: await GetIconPath(shortcut),
32-
IconDelegate: null,
33-
Platform: PlatformName
34-
);
29+
syncedGames.Add(new Game(
30+
title: Path.GetFileNameWithoutExtension(shortcut.FullName),
31+
runTask: GetGameRunTask(shortcut.FullName),
32+
iconPath: await GetIconPath(shortcut),
33+
iconDelegate: null,
34+
platform: PlatformName,
35+
uninstallAction: new(
36+
GetShortcutDeleteTask(shortcut.FullName),
37+
"Delete Shortcut"
38+
)
39+
));
3540
}
3641
}
42+
43+
SynchronizedGames = syncedGames;
3744
}
3845

3946
private Func<ActionContext, ValueTask<bool>> GetGameRunTask(string fullPath)
@@ -46,6 +53,15 @@ private Func<ActionContext, ValueTask<bool>> GetGameRunTask(string fullPath)
4653
};
4754
}
4855

56+
private Func<Task> GetShortcutDeleteTask(string fullPath)
57+
{
58+
return async () =>
59+
{
60+
File.Delete(fullPath);
61+
await SynchronizeGames();
62+
};
63+
}
64+
4965
private static async Task<string?> GetIconPath(FileInfo fileInfo)
5066
{
5167
if (fileInfo.Extension == ".url")

0 commit comments

Comments
 (0)