diff --git a/Cmdline/Action/AuthToken.cs b/Cmdline/Action/AuthToken.cs index d3767de85..9257e5761 100644 --- a/Cmdline/Action/AuthToken.cs +++ b/Cmdline/Action/AuthToken.cs @@ -33,7 +33,7 @@ public int RunSubCommand(GameInstanceManager? manager, string[] args = unparsed.options.ToArray(); int exitCode = Exit.OK; - Parser.Default.ParseArgumentsStrict(args, new AuthTokenSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(args, new AuthTokenSubOptions(), (option, suboptions) => { if (!string.IsNullOrEmpty(option) && suboptions != null) { diff --git a/Cmdline/Action/Cache.cs b/Cmdline/Action/Cache.cs index b8e5190ce..1b3725587 100644 --- a/Cmdline/Action/Cache.cs +++ b/Cmdline/Action/Cache.cs @@ -108,7 +108,7 @@ public int RunSubCommand(GameInstanceManager? mgr, int exitCode = Exit.OK; // Parse and process our sub-verbs - Parser.Default.ParseArgumentsStrict(args, new CacheSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(args, new CacheSubOptions(), (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) @@ -251,11 +251,20 @@ private void printCacheInfo() { if (manager?.Cache != null) { - manager.Cache.GetSizeInfo(out int fileCount, out long bytes, out long bytesFree); - user?.RaiseMessage(Properties.Resources.CacheInfo, - fileCount, - CkanModule.FmtSize(bytes), - CkanModule.FmtSize(bytesFree)); + manager.Cache.GetSizeInfo(out int fileCount, out long bytes, out long? bytesFree); + if (bytesFree.HasValue) + { + user?.RaiseMessage(Properties.Resources.CacheInfo, + fileCount, + CkanModule.FmtSize(bytes), + CkanModule.FmtSize(bytesFree.Value)); + } + else + { + user?.RaiseMessage(Properties.Resources.CacheInfoFreeSpaceUnknown, + fileCount, + CkanModule.FmtSize(bytes)); + } } } diff --git a/Cmdline/Action/Compat.cs b/Cmdline/Action/Compat.cs index 7b9b675de..b848475d6 100644 --- a/Cmdline/Action/Compat.cs +++ b/Cmdline/Action/Compat.cs @@ -99,7 +99,7 @@ public int RunSubCommand(GameInstanceManager? mgr, { var exitCode = Exit.OK; - Parser.Default.ParseArgumentsStrict(options.options.ToArray(), new CompatSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(options.options.ToArray(), new CompatSubOptions(), (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) diff --git a/Cmdline/Action/Filter.cs b/Cmdline/Action/Filter.cs index c303e07df..0c577197f 100644 --- a/Cmdline/Action/Filter.cs +++ b/Cmdline/Action/Filter.cs @@ -35,7 +35,7 @@ public int RunSubCommand(GameInstanceManager? mgr, string[] args = unparsed.options.ToArray(); int exitCode = Exit.OK; // Parse and process our sub-verbs - Parser.Default.ParseArgumentsStrict(args, new FilterSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(args, new FilterSubOptions(), (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) diff --git a/Cmdline/Action/GameInstance.cs b/Cmdline/Action/GameInstance.cs index 510ff78d6..7715f0519 100644 --- a/Cmdline/Action/GameInstance.cs +++ b/Cmdline/Action/GameInstance.cs @@ -181,7 +181,7 @@ public int RunSubCommand(GameInstanceManager? manager, int exitCode = Exit.OK; // Parse and process our sub-verbs - Parser.Default.ParseArgumentsStrict(args, new InstanceSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(args, new InstanceSubOptions(), (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) diff --git a/Cmdline/Action/Mark.cs b/Cmdline/Action/Mark.cs index 4ff6a039c..ec822bbf0 100644 --- a/Cmdline/Action/Mark.cs +++ b/Cmdline/Action/Mark.cs @@ -35,7 +35,7 @@ public int RunSubCommand(GameInstanceManager? mgr, string[] args = unparsed.options.ToArray(); int exitCode = Exit.OK; // Parse and process our sub-verbs - Parser.Default.ParseArgumentsStrict(args, new MarkSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(args, new MarkSubOptions(), (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) diff --git a/Cmdline/Action/Repair.cs b/Cmdline/Action/Repair.cs index 1b96778cd..17b9c1e88 100644 --- a/Cmdline/Action/Repair.cs +++ b/Cmdline/Action/Repair.cs @@ -58,7 +58,7 @@ public int RunSubCommand(GameInstanceManager? manager, { int exitCode = Exit.OK; // Parse and process our sub-verbs - Parser.Default.ParseArgumentsStrict(unparsed.options.ToArray(), new RepairSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(unparsed.options.ToArray(), new RepairSubOptions(), (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) diff --git a/Cmdline/Action/Repo.cs b/Cmdline/Action/Repo.cs index 731e95a3f..7e543c59d 100644 --- a/Cmdline/Action/Repo.cs +++ b/Cmdline/Action/Repo.cs @@ -137,7 +137,7 @@ public int RunSubCommand(GameInstanceManager? manager, int exitCode = Exit.OK; // Parse and process our sub-verbs - Parser.Default.ParseArgumentsStrict(args, new RepoSubOptions(), (string option, object suboptions) => + Parser.Default.ParseArgumentsStrict(args, new RepoSubOptions(), (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) @@ -200,8 +200,7 @@ private int AvailableRepositories(string? userAgent) is RepositoryList repoList) { var maxNameLen = repoList.repositories - .Select(r => r.name.Length) - .Max(); + .Max(r => r.name.Length); foreach (var repository in repoList.repositories) { user?.RaiseMessage(" {0}: {1}", diff --git a/Cmdline/Action/Stability.cs b/Cmdline/Action/Stability.cs index afba29f28..51cca23bc 100644 --- a/Cmdline/Action/Stability.cs +++ b/Cmdline/Action/Stability.cs @@ -19,7 +19,7 @@ public int RunSubCommand(GameInstanceManager? manager, int exitCode = Exit.OK; Parser.Default.ParseArgumentsStrict(options.options.ToArray(), new StabilitySubOptions(), - (string option, object suboptions) => + (option, suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) diff --git a/Cmdline/Properties/Resources.resx b/Cmdline/Properties/Resources.resx index d15e4519e..ea30a60f6 100644 --- a/Cmdline/Properties/Resources.resx +++ b/Cmdline/Properties/Resources.resx @@ -172,6 +172,7 @@ If you must run as an administrator, the `--asroot` parameter will bypass this c Can't reset cache path: {0} Unlimited {0} files, {1}, {2} free + {0} files, {1}, free space unknown "{0}" and "{1}" are the same versions. "{0}" is lower than "{1}". "{0}" is higher than "{1}". diff --git a/ConsoleUI/AuthTokenAddDialog.cs b/ConsoleUI/AuthTokenAddDialog.cs index 1c53b743b..34ab0ad95 100644 --- a/ConsoleUI/AuthTokenAddDialog.cs +++ b/ConsoleUI/AuthTokenAddDialog.cs @@ -57,10 +57,11 @@ public AuthTokenAddDialog(ConsoleTheme theme) : base(theme) AddObject(tokenEntry); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object sender) => false); + AddBinding(Keys.Escape, sender => false); AddTip(Properties.Resources.Enter, Properties.Resources.Accept, validKey); - AddBinding(Keys.Enter, (object sender) => { + AddBinding(Keys.Enter, sender => + { if (validKey()) { ServiceLocator.Container.Resolve().SetAuthToken(hostEntry.Value, tokenEntry.Value); return false; diff --git a/ConsoleUI/AuthTokenListScreen.cs b/ConsoleUI/AuthTokenListScreen.cs index 3f0f7b62a..c2fa2c5e6 100644 --- a/ConsoleUI/AuthTokenListScreen.cs +++ b/ConsoleUI/AuthTokenListScreen.cs @@ -36,10 +36,10 @@ public AuthTokenScreen(ConsoleTheme theme) : base(theme) new List>() { new ConsoleListBoxColumn( Properties.Resources.AuthTokenListHostHeader, - (string s) => s, null, 20), + s => s, null, 20), new ConsoleListBoxColumn( Properties.Resources.AuthTokenListTokenHeader, - (string s) => { + s => { return ServiceLocator.Container.Resolve().TryGetAuthToken(s, out string? token) ? token : Properties.Resources.AuthTokenListMissingToken; @@ -57,10 +57,11 @@ public AuthTokenScreen(ConsoleTheme theme) : base(theme) )); AddTip(Properties.Resources.Esc, Properties.Resources.Back); - AddBinding(Keys.Escape, (object sender) => false); + AddBinding(Keys.Escape, sender => false); tokenList.AddTip("A", Properties.Resources.Add); - tokenList.AddBinding(Keys.A, (object sender) => { + tokenList.AddBinding(Keys.A, sender => + { var ad = new AuthTokenAddDialog(theme); ad.Run(); DrawBackground(); @@ -69,7 +70,8 @@ public AuthTokenScreen(ConsoleTheme theme) : base(theme) }); tokenList.AddTip("R", Properties.Resources.Remove, () => tokenList.Selection != null); - tokenList.AddBinding(Keys.R, (object sender) => { + tokenList.AddBinding(Keys.R, sender => + { if (tokenList.Selection != null) { ServiceLocator.Container.Resolve().SetAuthToken(tokenList.Selection, null); tokenList.SetData(new List(ServiceLocator.Container.Resolve().GetAuthTokenHosts())); diff --git a/ConsoleUI/CompatibleVersionDialog.cs b/ConsoleUI/CompatibleVersionDialog.cs index df2068482..99ac24ec2 100644 --- a/ConsoleUI/CompatibleVersionDialog.cs +++ b/ConsoleUI/CompatibleVersionDialog.cs @@ -39,7 +39,8 @@ public CompatibleVersionDialog(ConsoleTheme theme, IGame game) : base(theme) ); AddObject(choices); choices.AddTip(Properties.Resources.Enter, Properties.Resources.CompatibleVersionsListAcceptTip); - choices.AddBinding(Keys.Enter, (object sender) => { + choices.AddBinding(Keys.Enter, sender => + { choice = choices.Selection; return false; }); @@ -51,7 +52,8 @@ public CompatibleVersionDialog(ConsoleTheme theme, IGame game) : base(theme) }; AddObject(manualEntry); manualEntry.AddTip(Properties.Resources.Enter, Properties.Resources.CompatibleVersionsEntryAcceptTip, () => GameVersion.TryParse(manualEntry.Value, out choice)); - manualEntry.AddBinding(Keys.Enter, (object sender) => { + manualEntry.AddBinding(Keys.Enter, sender => + { if (GameVersion.TryParse(manualEntry.Value, out choice)) { // Good value, done running return false; @@ -62,7 +64,8 @@ public CompatibleVersionDialog(ConsoleTheme theme, IGame game) : base(theme) }); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object StronglyTypedResourceBuilder) => { + AddBinding(Keys.Escape, StronglyTypedResourceBuilder => + { choice = null; return false; }); diff --git a/ConsoleUI/DeleteDirectoriesScreen.cs b/ConsoleUI/DeleteDirectoriesScreen.cs index 5e1d43bb2..06a37484c 100644 --- a/ConsoleUI/DeleteDirectoriesScreen.cs +++ b/ConsoleUI/DeleteDirectoriesScreen.cs @@ -51,7 +51,8 @@ public DeleteDirectoriesScreen(ConsoleTheme theme, directories.AddTip("D", Properties.Resources.DeleteDirectoriesDeleteDirTip, () => directories.Selection is not null && !toDelete.Contains(directories.Selection)); - directories.AddBinding(Keys.D, (object sender) => { + directories.AddBinding(Keys.D, sender => + { if (directories.Selection is not null) { toDelete.Add(directories.Selection); @@ -61,7 +62,8 @@ public DeleteDirectoriesScreen(ConsoleTheme theme, directories.AddTip("K", Properties.Resources.DeleteDirectoriesKeepDirTip, () => directories.Selection is not null && toDelete.Contains(directories.Selection)); - directories.AddBinding(Keys.K, (object sender) => { + directories.AddBinding(Keys.K, sender => + { if (directories.Selection is not null) { toDelete.Remove(directories.Selection); @@ -90,10 +92,11 @@ public DeleteDirectoriesScreen(ConsoleTheme theme, Properties.Resources.DeleteDirectoriesCancelTip); AddBinding(Keys.Escape, // Discard changes - (object sender) => false); + sender => false); AddTip("F9", Properties.Resources.DeleteDirectoriesApplyTip); - AddBinding(Keys.F9, (object sender) => { + AddBinding(Keys.F9, sender => + { foreach (var d in toDelete) { try { Directory.Delete(d, true); diff --git a/ConsoleUI/DependencyScreen.cs b/ConsoleUI/DependencyScreen.cs index c21ec3c3b..3345c5ceb 100644 --- a/ConsoleUI/DependencyScreen.cs +++ b/ConsoleUI/DependencyScreen.cs @@ -62,24 +62,25 @@ public DependencyScreen(ConsoleTheme theme, new List>() { new ConsoleListBoxColumn( Properties.Resources.RecommendationsInstallHeader, - (Dependency d) => StatusSymbol(d.module), + d => StatusSymbol(d.module), null, 7), new ConsoleListBoxColumn( Properties.Resources.RecommendationsNameHeader, - (Dependency d) => d.module.ToString(), + d => d.module.ToString(), null, null), new ConsoleListBoxColumn( Properties.Resources.RecommendationsSourcesHeader, - (Dependency d) => string.Join(", ", d.dependents), + d => string.Join(", ", d.dependents), null, 42) }, 1, 0, ListSortDirection.Descending ); dependencyList.AddTip("+", Properties.Resources.Toggle); - dependencyList.AddBinding(Keys.Plus, (object sender) => { + dependencyList.AddBinding(Keys.Plus, sender => + { if (dependencyList.Selection?.module is CkanModule mod && (accepted.Contains(mod) || TryWithoutConflicts(accepted.Append(mod)))) { ChangePlan.toggleContains(accepted, mod); @@ -88,7 +89,8 @@ public DependencyScreen(ConsoleTheme theme, }); dependencyList.AddTip($"{Properties.Resources.Ctrl}+A", Properties.Resources.SelectAll); - dependencyList.AddBinding(Keys.CtrlA, (object sender) => { + dependencyList.AddBinding(Keys.CtrlA, sender => + { if (TryWithoutConflicts(dependencies.Keys)) { foreach (var kvp in dependencies) { if (!accepted.Contains(kvp.Key)) { @@ -100,13 +102,15 @@ public DependencyScreen(ConsoleTheme theme, }); dependencyList.AddTip($"{Properties.Resources.Ctrl}+D", Properties.Resources.DeselectAll, () => accepted.Count > 0); - dependencyList.AddBinding(Keys.CtrlD, (object sender) => { + dependencyList.AddBinding(Keys.CtrlD, sender => + { accepted.Clear(); return true; }); dependencyList.AddTip(Properties.Resources.Enter, Properties.Resources.Details); - dependencyList.AddBinding(Keys.Enter, (object sender) => { + dependencyList.AddBinding(Keys.Enter, sender => + { if (dependencyList.Selection != null) { LaunchSubScreen(new ModInfoScreen(theme, manager, instance, reg, userAgent, plan, dependencyList.Selection.module, @@ -119,14 +123,16 @@ public DependencyScreen(ConsoleTheme theme, AddObject(dependencyList); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object sender) => { + AddBinding(Keys.Escape, sender => + { // Add everything to rejected rejected.UnionWith(dependencies.Keys.Select(m => m.identifier)); return false; }); AddTip("F9", Properties.Resources.Accept); - AddBinding(Keys.F9, (object sender) => { + AddBinding(Keys.F9, sender => + { if (TryWithoutConflicts(accepted)) { plan.Install.UnionWith(accepted); // Add the rest to rejected diff --git a/ConsoleUI/DownloadImportDialog.cs b/ConsoleUI/DownloadImportDialog.cs index 0ead56d4b..e5ad6e365 100644 --- a/ConsoleUI/DownloadImportDialog.cs +++ b/ConsoleUI/DownloadImportDialog.cs @@ -41,7 +41,7 @@ public static void ImportDownloads(ConsoleTheme theme, Properties.Resources.ImportProgressTitle, Properties.Resources.ImportProgressMessage); ps.Run(() => ModuleInstaller.ImportFiles(files, ps, - (CkanModule mod) => cp.Install.Add(mod), + mod => cp.Install.Add(mod), RegistryManager.Instance(gameInst, repoData).registry, gameInst, cache)); } diff --git a/ConsoleUI/GameInstanceEditScreen.cs b/ConsoleUI/GameInstanceEditScreen.cs index 17f940808..176da7966 100644 --- a/ConsoleUI/GameInstanceEditScreen.cs +++ b/ConsoleUI/GameInstanceEditScreen.cs @@ -89,13 +89,15 @@ public GameInstanceEditScreen(ConsoleTheme theme, ); AddObject(repoList); repoList.AddTip("A", Properties.Resources.Add); - repoList.AddBinding(Keys.A, (object sender) => { + repoList.AddBinding(Keys.A, sender => + { LaunchSubScreen(new RepoAddScreen(theme, instance.game, repoEditList, userAgent)); repoList.SetData(new List(repoEditList.Values)); return true; }); repoList.AddTip("R", Properties.Resources.Remove); - repoList.AddBinding(Keys.R, (object sender) => { + repoList.AddBinding(Keys.R, sender => + { if (repoList.Selection is Repository repo) { int oldPrio = repo.priority; @@ -111,7 +113,8 @@ public GameInstanceEditScreen(ConsoleTheme theme, return true; }); repoList.AddTip("E", Properties.Resources.Edit); - repoList.AddBinding(Keys.E, (object sender) => { + repoList.AddBinding(Keys.E, sender => + { if (repoList.Selection is Repository repo) { LaunchSubScreen(new RepoEditScreen(theme, instance.game, repoEditList, repo, userAgent)); @@ -120,7 +123,8 @@ public GameInstanceEditScreen(ConsoleTheme theme, return true; }); repoList.AddTip("-", Properties.Resources.Up); - repoList.AddBinding(Keys.Minus, (object sender) => { + repoList.AddBinding(Keys.Minus, sender => + { if (repoList.Selection is Repository repo) { if (repo.priority > 0) { @@ -136,7 +140,8 @@ public GameInstanceEditScreen(ConsoleTheme theme, return true; }); repoList.AddTip("+", Properties.Resources.Down); - repoList.AddBinding(Keys.Plus, (object sender) => { + repoList.AddBinding(Keys.Plus, sender => + { if (repoList.Selection is Repository repo) { var next = SortedDictFind(repoEditList, @@ -165,7 +170,8 @@ public GameInstanceEditScreen(ConsoleTheme theme, AddObject(compatList); compatList.AddTip("A", Properties.Resources.Add); - compatList.AddBinding(Keys.A, (object sender) => { + compatList.AddBinding(Keys.A, sender => + { CompatibleVersionDialog vd = new CompatibleVersionDialog(theme, instance.game); var newVersion = vd.Run(); DrawBackground(); @@ -176,7 +182,8 @@ public GameInstanceEditScreen(ConsoleTheme theme, return true; }); compatList.AddTip("R", Properties.Resources.Remove, () => compatList.Selection != null); - compatList.AddBinding(Keys.R, (object sender) => { + compatList.AddBinding(Keys.R, sender => + { if (compatList.Selection is GameVersion gv) { compatEditList.Remove(gv); diff --git a/ConsoleUI/GameInstanceListScreen.cs b/ConsoleUI/GameInstanceListScreen.cs index d136cdb59..6cb7945ab 100644 --- a/ConsoleUI/GameInstanceListScreen.cs +++ b/ConsoleUI/GameInstanceListScreen.cs @@ -71,15 +71,16 @@ public GameInstanceListScreen(ConsoleTheme theme, if (first) { AddTip($"{Properties.Resources.Ctrl}+Q", Properties.Resources.Quit); - AddBinding(Keys.AltX, (object sender) => false); - AddBinding(Keys.CtrlQ, (object sender) => false); + AddBinding(Keys.AltX, sender => false); + AddBinding(Keys.CtrlQ, sender => false); } else { AddTip(Properties.Resources.Esc, Properties.Resources.Quit); - AddBinding(Keys.Escape, (object sender) => false); + AddBinding(Keys.Escape, sender => false); } AddTip(Properties.Resources.Enter, Properties.Resources.Select); - AddBinding(Keys.Enter, (object sender) => { + AddBinding(Keys.Enter, sender => + { if (instanceList.Selection is GameInstance inst) { var d = new ConsoleMessageDialog(theme, string.Format(Properties.Resources.InstanceListLoadingInstance, @@ -87,7 +88,7 @@ public GameInstanceListScreen(ConsoleTheme theme, new List()); if (TryGetInstance(theme, inst, repoData, - (ConsoleTheme th) => { d.Run(() => {}); }, + th => { d.Run(() => {}); }, null)) { try { manager.SetCurrentInstance(inst.Name); @@ -105,13 +106,15 @@ public GameInstanceListScreen(ConsoleTheme theme, }); instanceList.AddTip("A", Properties.Resources.Add); - instanceList.AddBinding(Keys.A, (object sender) => { + instanceList.AddBinding(Keys.A, sender => + { LaunchSubScreen(new GameInstanceAddScreen(theme, manager)); instanceList.SetData(manager.Instances.Values); return true; }); instanceList.AddTip("R", Properties.Resources.Remove); - instanceList.AddBinding(Keys.R, (object sender) => { + instanceList.AddBinding(Keys.R, sender => + { if (instanceList.Selection is GameInstance inst) { manager.RemoveInstance(inst.Name); @@ -120,7 +123,8 @@ public GameInstanceListScreen(ConsoleTheme theme, return true; }); instanceList.AddTip("E", Properties.Resources.Edit); - instanceList.AddBinding(Keys.E, (object sender) => { + instanceList.AddBinding(Keys.E, sender => + { if (instanceList.Selection is GameInstance inst) { var d = new ConsoleMessageDialog( @@ -128,7 +132,7 @@ public GameInstanceListScreen(ConsoleTheme theme, string.Format(Properties.Resources.InstanceListLoadingInstance, inst.Name), new List()); TryGetInstance(theme, inst, repoData, - (ConsoleTheme th) => { d.Run(() => {}); }, + th => { d.Run(() => {}); }, null); // Still launch the screen even if the load fails, // because you need to be able to fix the name/path. @@ -138,7 +142,8 @@ public GameInstanceListScreen(ConsoleTheme theme, }); instanceList.AddTip("D", Properties.Resources.InstanceListDefaultToggle); - instanceList.AddBinding(Keys.D, (object sender) => { + instanceList.AddBinding(Keys.D, sender => + { if (instanceList.Selection is GameInstance inst) { string name = inst.Name; diff --git a/ConsoleUI/GameInstanceScreen.cs b/ConsoleUI/GameInstanceScreen.cs index 814319f5b..5037f9b6b 100644 --- a/ConsoleUI/GameInstanceScreen.cs +++ b/ConsoleUI/GameInstanceScreen.cs @@ -22,7 +22,8 @@ protected GameInstanceScreen(ConsoleTheme theme, GameInstanceManager mgr, string manager = mgr; AddTip("F2", Properties.Resources.Accept); - AddBinding(Keys.F2, (object sender) => { + AddBinding(Keys.F2, sender => + { if (Valid()) { Save(); // Close screen @@ -34,7 +35,8 @@ protected GameInstanceScreen(ConsoleTheme theme, GameInstanceManager mgr, string }); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object sender) => { + AddBinding(Keys.Escape, sender => + { // Discard changes return false; }); diff --git a/ConsoleUI/InstallFilterAddDialog.cs b/ConsoleUI/InstallFilterAddDialog.cs index a018b865c..a57dbc25a 100644 --- a/ConsoleUI/InstallFilterAddDialog.cs +++ b/ConsoleUI/InstallFilterAddDialog.cs @@ -28,13 +28,15 @@ public InstallFilterAddDialog(ConsoleTheme theme) : base(theme) }; AddObject(manualEntry); manualEntry.AddTip(Properties.Resources.Enter, Properties.Resources.FilterAddAcceptTip); - manualEntry.AddBinding(Keys.Enter, (object sender) => { + manualEntry.AddBinding(Keys.Enter, sender => + { choice = manualEntry.Value; return false; }); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object sender) => { + AddBinding(Keys.Escape, sender => + { choice = null; return false; }); diff --git a/ConsoleUI/InstallFiltersScreen.cs b/ConsoleUI/InstallFiltersScreen.cs index 79f575786..0e7f4ac1d 100644 --- a/ConsoleUI/InstallFiltersScreen.cs +++ b/ConsoleUI/InstallFiltersScreen.cs @@ -27,13 +27,15 @@ public InstallFiltersScreen(ConsoleTheme theme, IConfiguration globalConfig, Gam instanceFilters = instance.InstallFilters.ToList(); AddTip("F2", Properties.Resources.Accept); - AddBinding(Keys.F2, (object sender) => { + AddBinding(Keys.F2, sender => + { Save(); // Close screen return false; }); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object sender) => { + AddBinding(Keys.Escape, sender => + { // Discard changes return false; }); @@ -60,12 +62,14 @@ public InstallFiltersScreen(ConsoleTheme theme, IConfiguration globalConfig, Gam ); AddObject(globalList); globalList.AddTip("A", Properties.Resources.Add); - globalList.AddBinding(Keys.A, (object sender) => { + globalList.AddBinding(Keys.A, sender => + { AddFilter(theme, globalList, globalFilters); return true; }); globalList.AddTip("R", Properties.Resources.Remove); - globalList.AddBinding(Keys.R, (object sender) => { + globalList.AddBinding(Keys.R, sender => + { RemoveFilter(globalList, globalFilters); return true; }); @@ -83,12 +87,14 @@ public InstallFiltersScreen(ConsoleTheme theme, IConfiguration globalConfig, Gam ); AddObject(instanceList); instanceList.AddTip("A", Properties.Resources.Add); - instanceList.AddBinding(Keys.A, (object sender) => { + instanceList.AddBinding(Keys.A, sender => + { AddFilter(theme, instanceList, instanceFilters); return true; }); instanceList.AddTip("R", Properties.Resources.Remove); - instanceList.AddBinding(Keys.R, (object sender) => { + instanceList.AddBinding(Keys.R, sender => + { RemoveFilter(instanceList, instanceFilters); return true; }); diff --git a/ConsoleUI/InstallScreen.cs b/ConsoleUI/InstallScreen.cs index 047d65800..5a8add8e5 100644 --- a/ConsoleUI/InstallScreen.cs +++ b/ConsoleUI/InstallScreen.cs @@ -157,7 +157,7 @@ public override void Run(Action? process = null) ex.Message, Properties.Resources.InstallTooManyModsNameHeader, ex.modules, - (CkanModule mod) => mod.ToString() + mod => mod.ToString() ); var chosen = ch.Run(); DrawBackground(); diff --git a/ConsoleUI/ModInfoScreen.cs b/ConsoleUI/ModInfoScreen.cs index a45b6891d..f0c144037 100644 --- a/ConsoleUI/ModInfoScreen.cs +++ b/ConsoleUI/ModInfoScreen.cs @@ -145,12 +145,13 @@ public ModInfoScreen(ConsoleTheme theme, } AddTip(Properties.Resources.Esc, Properties.Resources.Back); - AddBinding(Keys.Escape, (object sender) => false); + AddBinding(Keys.Escape, sender => false); AddTip($"{Properties.Resources.Ctrl}+D", Properties.Resources.ModInfoDownloadToCache, () => manager.Cache != null && !manager.Cache.IsMaybeCachedZip(mod) && !mod.IsDLC ); - AddBinding(Keys.CtrlD, (object sender) => { + AddBinding(Keys.CtrlD, sender => + { if (!mod.IsDLC) { Download(); } diff --git a/ConsoleUI/ModListScreen.cs b/ConsoleUI/ModListScreen.cs index cbac86c35..ab82f9d92 100644 --- a/ConsoleUI/ModListScreen.cs +++ b/ConsoleUI/ModListScreen.cs @@ -82,7 +82,7 @@ is int i and > 0 12), }, 1, 0, ListSortDirection.Descending, - (CkanModule m, string filter) => { + (m, filter) => { // Search for author if (filter.StartsWith("@")) { string authorFilt = filter[1..]; @@ -149,7 +149,7 @@ is int i and > 0 ? Properties.Resources.ModListSearchFocusedGhostText : Properties.Resources.ModListSearchUnfocusedGhostText }; - searchBox.OnChange += (ConsoleField sender, string newValue) => { + searchBox.OnChange += (sender, newValue) => { moduleList.FilterString = newValue; }; @@ -167,34 +167,39 @@ is int i and > 0 AddObject(searchBox); AddObject(moduleList); - AddBinding(Keys.CtrlP, (object sender) => PlayGame()); - AddBinding(Keys.CtrlQ, (object sender) => false); - AddBinding(Keys.AltX, (object sender) => false); - AddBinding(Keys.F1, (object sender) => Help()); - AddBinding(Keys.AltH, (object sender) => Help()); - AddBinding(Keys.F5, (object sender) => UpdateRegistry()); - AddBinding(Keys.CtrlR, (object sender) => UpdateRegistry()); - AddBinding(Keys.CtrlU, (object sender) => UpgradeAll()); + AddBinding(Keys.CtrlP, sender => PlayGame()); + AddBinding(Keys.CtrlQ, sender => false); + AddBinding(Keys.AltX, sender => false); + AddBinding(Keys.F1, sender => Help()); + AddBinding(Keys.AltH, sender => Help()); + AddBinding(Keys.F5, sender => UpdateRegistry()); + AddBinding(Keys.CtrlR, sender => UpdateRegistry()); + AddBinding(Keys.CtrlU, sender => UpgradeAll()); // Now a bunch of convenience shortcuts so you don't get stuck in the search box - searchBox.AddBinding(Keys.PageUp, (object sender) => { + searchBox.AddBinding(Keys.PageUp, sender => + { SetFocus(moduleList); return true; }); - searchBox.AddBinding(Keys.PageDown, (object sender) => { + searchBox.AddBinding(Keys.PageDown, sender => + { SetFocus(moduleList); return true; }); - searchBox.AddBinding(Keys.Enter, (object sender) => { + searchBox.AddBinding(Keys.Enter, sender => + { SetFocus(moduleList); return true; }); - moduleList.AddBinding(Keys.CtrlF, (object sender) => { + moduleList.AddBinding(Keys.CtrlF, sender => + { SetFocus(searchBox); return true; }); - moduleList.AddBinding(Keys.Escape, (object sender) => { + moduleList.AddBinding(Keys.Escape, sender => + { searchBox.Clear(); return true; }); @@ -202,7 +207,8 @@ is int i and > 0 moduleList.AddTip(Properties.Resources.Enter, Properties.Resources.Details, () => moduleList.Selection != null ); - moduleList.AddBinding(Keys.Enter, (object sender) => { + moduleList.AddBinding(Keys.Enter, sender => + { if (moduleList.Selection != null && manager.CurrentInstance != null) { LaunchSubScreen(new ModInfoScreen(theme, manager, manager.CurrentInstance, registry, userAgent, plan, moduleList.Selection, upgradeableGroups?[true], debug)); @@ -227,7 +233,8 @@ is int i and > 0 manager.CurrentInstance.StabilityToleranceConfig, manager.CurrentInstance.VersionCriteria()) != null ); - moduleList.AddBinding(Keys.Plus, (object sender) => { + moduleList.AddBinding(Keys.Plus, sender => + { if (moduleList.Selection != null && !moduleList.Selection.IsDLC && manager.CurrentInstance != null) { if (!registry.IsInstalled(moduleList.Selection.identifier, false)) { plan.ToggleInstall(moduleList.Selection); @@ -248,7 +255,8 @@ is int i and > 0 && registry.IsInstalled(moduleList.Selection.identifier, false) && !registry.IsAutodetected(moduleList.Selection.identifier) ); - moduleList.AddBinding(Keys.Minus, (object sender) => { + moduleList.AddBinding(Keys.Minus, sender => + { if (moduleList.Selection != null && !moduleList.Selection.IsDLC && registry.IsInstalled(moduleList.Selection.identifier, false) && !registry.IsAutodetected(moduleList.Selection.identifier)) { @@ -265,7 +273,8 @@ is int i and > 0 () => moduleList.Selection != null && !moduleList.Selection.IsDLC && (registry.InstalledModule(moduleList.Selection.identifier)?.AutoInstalled ?? false) ); - moduleList.AddBinding(Keys.F8, (object sender) => { + moduleList.AddBinding(Keys.F8, sender => + { if (moduleList.Selection is CkanModule m) { var im = registry.InstalledModule(m.identifier); @@ -278,7 +287,8 @@ is int i and > 0 }); AddTip("F9", Properties.Resources.ModListApplyChangesTip, plan.NonEmpty); - AddBinding(Keys.F9, (object sender) => { + AddBinding(Keys.F9, sender => + { ApplyChanges(); return true; }); @@ -298,7 +308,8 @@ is int i and > 0 : string.Format(Properties.Resources.ModListUpdatedDaysAgo, days); }, null, - (ConsoleTheme th) => { + th => + { return timeSinceUpdate < RepositoryDataManager.TimeTillStale ? th.RegistryUpToDate : timeSinceUpdate < RepositoryDataManager.TimeTillVeryStale ? th.RegistryStale : th.RegistryVeryStale; diff --git a/ConsoleUI/ProgressScreen.cs b/ConsoleUI/ProgressScreen.cs index 3df28ff08..48c397a82 100644 --- a/ConsoleUI/ProgressScreen.cs +++ b/ConsoleUI/ProgressScreen.cs @@ -79,11 +79,13 @@ public override bool RaiseYesNoDialog(string question) TextAlign.Center, -Console.WindowHeight / 2 ); - d.AddBinding(Keys.Y, (object sender) => { + d.AddBinding(Keys.Y, sender => + { d.PressButton(0); return false; }); - d.AddBinding(Keys.N, (object sender) => { + d.AddBinding(Keys.N, sender => + { d.PressButton(1); return false; }); diff --git a/ConsoleUI/RepoScreen.cs b/ConsoleUI/RepoScreen.cs index 9a131838a..42384296e 100644 --- a/ConsoleUI/RepoScreen.cs +++ b/ConsoleUI/RepoScreen.cs @@ -43,7 +43,8 @@ protected RepoScreen(ConsoleTheme theme, AddObject(url); AddTip("F2", Properties.Resources.Accept); - AddBinding(Keys.F2, (object sender) => { + AddBinding(Keys.F2, sender => + { if (Valid()) { Save(); return false; @@ -53,7 +54,7 @@ protected RepoScreen(ConsoleTheme theme, }); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object sender) => false); + AddBinding(Keys.Escape, sender => false); // mainMenu = list of default options mainMenu = (RepositoryList.DefaultRepositories(game, userAgent) is RepositoryList repoList) diff --git a/ConsoleUI/SplashScreen.cs b/ConsoleUI/SplashScreen.cs index 623c01692..74de975ff 100644 --- a/ConsoleUI/SplashScreen.cs +++ b/ConsoleUI/SplashScreen.cs @@ -31,7 +31,7 @@ public bool Run(ConsoleTheme theme) GameInstance? ksp = manager.CurrentInstance ?? manager.GetPreferredInstance(); if (ksp != null && !GameInstanceListScreen.TryGetInstance(theme, ksp, repoData, - (ConsoleTheme th) => Draw(th, false), + th => Draw(th, false), new ProgressImmediate(p => drawProgressBar(theme, 22, 20, p)))) { Console.ResetColor(); Console.Clear(); diff --git a/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs b/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs index 6c38d78e7..f9df368cb 100644 --- a/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs +++ b/ConsoleUI/Toolkit/ConsoleChoiceDialog.cs @@ -56,12 +56,14 @@ public ConsoleChoiceDialog(ConsoleTheme theme, string m, string hdr, List { + choices.AddBinding(Keys.Enter, sender => + { return false; }); choices.AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - choices.AddBinding(Keys.Escape, (object sender) => { + choices.AddBinding(Keys.Escape, sender => + { cancelled = true; return false; }); diff --git a/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs b/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs index fb46779ac..30f60d18e 100644 --- a/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs +++ b/ConsoleUI/Toolkit/ConsoleFileMultiSelectDialog.cs @@ -83,7 +83,7 @@ public ConsoleFileMultiSelectDialog(ConsoleTheme theme, 9), new ConsoleListBoxColumn( Properties.Resources.FileSelectTimestampHeader, - (FileSystemInfo fi) => fi.LastWriteTime.ToString("yyyy-MM-dd"), + fi => fi.LastWriteTime.ToString("yyyy-MM-dd"), (a, b) => a.LastWriteTime.CompareTo(b.LastWriteTime), 10) }, @@ -92,13 +92,15 @@ public ConsoleFileMultiSelectDialog(ConsoleTheme theme, AddObject(fileList); AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); - AddBinding(Keys.Escape, (object sender) => { + AddBinding(Keys.Escape, sender => + { chosenFiles.Clear(); return false; }); AddTip(ConsoleScreen.MainMenuKeyTip, Properties.Resources.Sort); - AddBinding(ConsoleScreen.MainMenuKeys, (object sender) => { + AddBinding(ConsoleScreen.MainMenuKeys, sender => + { fileList.SortMenu().Run(theme, right - 2, top + 2); DrawBackground(); return true; @@ -106,11 +108,12 @@ public ConsoleFileMultiSelectDialog(ConsoleTheme theme, AddTip(Properties.Resources.Enter, Properties.Resources.FileSelectChangeDirectory, () => fileList.Selection != null && isDir(fileList.Selection)); AddTip(Properties.Resources.Enter, Properties.Resources.FileSelectSelect, () => fileList.Selection != null && !isDir(fileList.Selection)); - AddBinding(Keys.Enter, (object sender) => selectRow()); - AddBinding(Keys.Space, (object sender) => selectRow()); + AddBinding(Keys.Enter, sender => selectRow()); + AddBinding(Keys.Space, sender => selectRow()); AddTip($"{Properties.Resources.Ctrl}+A", Properties.Resources.SelectAll); - AddBinding(Keys.CtrlA, (object sender) => { + AddBinding(Keys.CtrlA, sender => + { foreach (FileSystemInfo fi in contents) { if (!isDir(fi)) { if (fi is FileInfo file) @@ -123,7 +126,8 @@ public ConsoleFileMultiSelectDialog(ConsoleTheme theme, }); AddTip($"{Properties.Resources.Ctrl}+D", Properties.Resources.DeselectAll, () => chosenFiles.Count > 0); - AddBinding(Keys.CtrlD, (object sender) => { + AddBinding(Keys.CtrlD, sender => + { if (chosenFiles.Count > 0) { chosenFiles.Clear(); } @@ -131,7 +135,7 @@ public ConsoleFileMultiSelectDialog(ConsoleTheme theme, }); AddTip("F9", acceptTip, () => chosenFiles.Count > 0); - AddBinding(Keys.F9, (object sender) => false); + AddBinding(Keys.F9, sender => false); } private bool selectRow() diff --git a/ConsoleUI/Toolkit/ConsoleListBox.cs b/ConsoleUI/Toolkit/ConsoleListBox.cs index 9909ab2ce..66d7b48bc 100644 --- a/ConsoleUI/Toolkit/ConsoleListBox.cs +++ b/ConsoleUI/Toolkit/ConsoleListBox.cs @@ -142,8 +142,7 @@ public override void Draw(ConsoleTheme theme, bool focused) } var remainingWidth = contentR - l - 1 - - columns.Select(col => col.Width ?? 0) - .Sum() + - columns.Sum(col => col.Width ?? 0) - (padding.Length * (columns.Count - 1)); var autoWidthCount = columns.Count(col => !col.Width.HasValue); var autoWidth = autoWidthCount > 0 && remainingWidth > 0 diff --git a/ConsoleUI/Toolkit/ConsoleScreen.cs b/ConsoleUI/Toolkit/ConsoleScreen.cs index 161a6d7b4..08d3b5245 100644 --- a/ConsoleUI/Toolkit/ConsoleScreen.cs +++ b/ConsoleUI/Toolkit/ConsoleScreen.cs @@ -22,7 +22,8 @@ protected ConsoleScreen(ConsoleTheme theme) MainMenuKeyTip, MenuTip(), () => mainMenu != null ); - AddBinding(MainMenuKeys, (object sender) => { + AddBinding(MainMenuKeys, sender => + { bool val = true; if (mainMenu != null) { DrawSelectedHamburger(); @@ -111,11 +112,13 @@ public virtual bool RaiseYesNoDialog(string question) Properties.Resources.Yes, Properties.Resources.No }); - d.AddBinding(Keys.Y, (object sender) => { + d.AddBinding(Keys.Y, sender => + { d.PressButton(0); return false; }); - d.AddBinding(Keys.N, (object sender) => { + d.AddBinding(Keys.N, sender => + { d.PressButton(1); return false; }); diff --git a/ConsoleUI/Toolkit/ConsoleTextBox.cs b/ConsoleUI/Toolkit/ConsoleTextBox.cs index e95cf7181..e56b273f7 100644 --- a/ConsoleUI/Toolkit/ConsoleTextBox.cs +++ b/ConsoleUI/Toolkit/ConsoleTextBox.cs @@ -180,58 +180,70 @@ public override void Draw(ConsoleTheme theme, bool focused) public void AddScrollBindings(ScreenContainer cont, ConsoleTheme theme, bool drawMore = false) { if (drawMore) { - cont.AddBinding(Keys.Home, (object sender) => { + cont.AddBinding(Keys.Home, sender => + { ScrollToTop(); Draw(theme, false); return true; }); - cont.AddBinding(Keys.End, (object sender) => { + cont.AddBinding(Keys.End, sender => + { ScrollToBottom(); Draw(theme, false); return true; }); - cont.AddBinding(Keys.PageUp, (object sender) => { + cont.AddBinding(Keys.PageUp, sender => + { ScrollUp(); Draw(theme, false); return true; }); - cont.AddBinding(Keys.PageDown, (object sender) => { + cont.AddBinding(Keys.PageDown, sender => + { ScrollDown(); Draw(theme, false); return true; }); - cont.AddBinding(Keys.UpArrow, (object sender) => { + cont.AddBinding(Keys.UpArrow, sender => + { ScrollUp(1); Draw(theme, false); return true; }); - cont.AddBinding(Keys.DownArrow, (object sender) => { + cont.AddBinding(Keys.DownArrow, sender => + { ScrollDown(1); Draw(theme, false); return true; }); } else { - cont.AddBinding(Keys.Home, (object sender) => { + cont.AddBinding(Keys.Home, sender => + { ScrollToTop(); return true; }); - cont.AddBinding(Keys.End, (object sender) => { + cont.AddBinding(Keys.End, sender => + { ScrollToBottom(); return true; }); - cont.AddBinding(Keys.PageUp, (object sender) => { + cont.AddBinding(Keys.PageUp, sender => + { ScrollUp(); return true; }); - cont.AddBinding(Keys.PageDown, (object sender) => { + cont.AddBinding(Keys.PageDown, sender => + { ScrollDown(); return true; }); - cont.AddBinding(Keys.UpArrow, (object sender) => { + cont.AddBinding(Keys.UpArrow, sender => + { ScrollUp(1); return true; }); - cont.AddBinding(Keys.DownArrow, (object sender) => { + cont.AddBinding(Keys.DownArrow, sender => + { ScrollDown(1); return true; }); diff --git a/ConsoleUI/Toolkit/ScreenContainer.cs b/ConsoleUI/Toolkit/ScreenContainer.cs index f3305cf6e..1c5dc58a8 100644 --- a/ConsoleUI/Toolkit/ScreenContainer.cs +++ b/ConsoleUI/Toolkit/ScreenContainer.cs @@ -15,7 +15,8 @@ public abstract class ScreenContainer { protected ScreenContainer(ConsoleTheme theme) { this.theme = theme; - AddBinding(Keys.CtrlL, (object sender) => { + AddBinding(Keys.CtrlL, sender => + { // Just redraw everything and keep running DrawBackground(); return true; diff --git a/Core/CKANPathUtils.cs b/Core/CKANPathUtils.cs index ec2c8f5fc..7c0646eec 100644 --- a/Core/CKANPathUtils.cs +++ b/Core/CKANPathUtils.cs @@ -79,7 +79,7 @@ public static string ToRelative(string path, string root) } // Strip off the root, then remove any slashes at the beginning - return path.Remove(0, root.Length).TrimStart('/'); + return path[root.Length..].TrimStart('/'); } /// @@ -118,9 +118,9 @@ public static void CheckFreeSpace(DirectoryInfo where, long bytesToStore, string errorDescription) { - if (bytesToStore > 0) + if (bytesToStore > 0 + && where.GetDrive()?.AvailableFreeSpace is long bytesFree) { - var bytesFree = where.GetDrive().AvailableFreeSpace; if (bytesToStore > bytesFree) { throw new NotEnoughSpaceKraken(errorDescription, where, bytesFree, bytesToStore); diff --git a/Core/Extensions/IOExtensions.cs b/Core/Extensions/IOExtensions.cs index 299ea2740..f82a0ace2 100644 --- a/Core/Extensions/IOExtensions.cs +++ b/Core/Extensions/IOExtensions.cs @@ -14,8 +14,8 @@ public static class IOExtensions /// /// Any DirectoryInfo object /// The DriveInfo associated with this directory, if any, else null - public static DriveInfo GetDrive(this DirectoryInfo dir) - => new DriveInfo(dir.FullName); + public static DriveInfo? GetDrive(this DirectoryInfo dir) + => Utilities.DefaultIfThrows(() => new DriveInfo(dir.FullName)); /// /// A version of Stream.CopyTo with progress updates. diff --git a/Core/GameInstanceManager.cs b/Core/GameInstanceManager.cs index 90a784051..f0e6b1648 100644 --- a/Core/GameInstanceManager.cs +++ b/Core/GameInstanceManager.cs @@ -13,7 +13,6 @@ using CKAN.Configuration; using CKAN.Games; using CKAN.Games.KerbalSpaceProgram; -using CKAN.Extensions; using CKAN.Games.KerbalSpaceProgram.GameVersionProviders; namespace CKAN @@ -615,23 +614,24 @@ public bool TrySetupCache(string? path, } else { - // Make sure we can access it - var bytesFree = new DirectoryInfo(path).GetDrive().AvailableFreeSpace; Cache = new NetModuleCache(this, path); Configuration.DownloadCacheDir = path; } if (origPath != null && origCache != null) { origCache.GetSizeInfo(out _, out long oldNumBytes, out _); - Cache.GetSizeInfo(out _, out _, out long bytesFree); + Cache.GetSizeInfo(out _, out _, out long? bytesFree); if (oldNumBytes > 0) { switch (User.RaiseSelectionDialog( - string.Format(Properties.Resources.GameInstanceManagerCacheMigrationPrompt, - CkanModule.FmtSize(oldNumBytes), - CkanModule.FmtSize(bytesFree)), - oldNumBytes < bytesFree ? 0 : 2, + bytesFree.HasValue + ? string.Format(Properties.Resources.GameInstanceManagerCacheMigrationPrompt, + CkanModule.FmtSize(oldNumBytes), + CkanModule.FmtSize(bytesFree.Value)) + : string.Format(Properties.Resources.GameInstanceManagerCacheMigrationPromptFreeSpaceUnknown, + CkanModule.FmtSize(oldNumBytes)), + oldNumBytes < (bytesFree ?? 0) ? 0 : 2, Properties.Resources.GameInstanceManagerCacheMigrationMove, Properties.Resources.GameInstanceManagerCacheMigrationDelete, Properties.Resources.GameInstanceManagerCacheMigrationOpen, diff --git a/Core/Net/IDownloader.cs b/Core/Net/IDownloader.cs index 211e3c6ae..114363b5b 100644 --- a/Core/Net/IDownloader.cs +++ b/Core/Net/IDownloader.cs @@ -14,7 +14,7 @@ public interface IDownloader /// void DownloadModules(IEnumerable modules); - public event Action OverallDownloadProgress; + event Action OverallDownloadProgress; /// /// Raised when data arrives for a module diff --git a/Core/Net/NetAsyncModulesDownloader.cs b/Core/Net/NetAsyncModulesDownloader.cs index ffb5b7f15..f780517d4 100644 --- a/Core/Net/NetAsyncModulesDownloader.cs +++ b/Core/Net/NetAsyncModulesDownloader.cs @@ -84,8 +84,7 @@ public void DownloadModules(IEnumerable modules) .ToHashSet(); var moduleGroups = CkanModule.GroupByDownloads(modules); // Make sure we have enough space to download and cache - cache.CheckFreeSpace(moduleGroups.Select(grp => grp.First().download_size) - .Sum()); + cache.CheckFreeSpace(moduleGroups.Sum(grp => grp.First().download_size)); // Add all the requested modules this.modules.AddRange(moduleGroups.SelectMany(grp => grp)); diff --git a/Core/Net/NetFileCache.cs b/Core/Net/NetFileCache.cs index f753270ca..73692d3a8 100644 --- a/Core/Net/NetFileCache.cs +++ b/Core/Net/NetFileCache.cs @@ -69,9 +69,6 @@ public NetFileCache(string path) } inProgressPath = new DirectoryInfo(Path.Combine(path, "downloading")); - // Make sure we can access it - var bytesFree = cachePath.GetDrive().AvailableFreeSpace; - // Establish a watch on our cache. This means we can cache the directory contents, // and discard that cache if we spot changes. watcher = new FileSystemWatcher(cachePath.FullName, "*.zip") @@ -257,9 +254,9 @@ public bool IsMaybeCachedZip(Uri url, DateTime? remoteTimestamp = null) /// Output parameter set to number of files in cache /// Output parameter set to number of bytes in cache /// Output parameter set to number of bytes free - public void GetSizeInfo(out int numFiles, out long numBytes, out long bytesFree) + public void GetSizeInfo(out int numFiles, out long numBytes, out long? bytesFree) { - bytesFree = cachePath.GetDrive().AvailableFreeSpace; + bytesFree = cachePath.GetDrive()?.AvailableFreeSpace; (numFiles, numBytes) = Enumerable.Repeat(cachePath, 1) .Concat(legacyDirs()) .Select(GetDirSizeInfo) @@ -292,7 +289,7 @@ private IEnumerable legacyDirs() public void EnforceSizeLimit(long bytes, Registry registry) { - GetSizeInfo(out int numFiles, out long curBytes, out long _); + GetSizeInfo(out int numFiles, out long curBytes, out _); if (curBytes > bytes) { // This object will let us determine whether a module is compatible with any of our instances diff --git a/Core/Net/NetModuleCache.cs b/Core/Net/NetModuleCache.cs index cab42cbb5..165ce2b2b 100644 --- a/Core/Net/NetModuleCache.cs +++ b/Core/Net/NetModuleCache.cs @@ -85,7 +85,7 @@ public bool IsMaybeCachedZip(CkanModule m) public string? GetCachedFilename(CkanModule m) => m.download?.Select(dlUri => cache.GetCachedFilename(dlUri, m.release_date)) .FirstOrDefault(filename => filename != null); - public void GetSizeInfo(out int numFiles, out long numBytes, out long bytesFree) + public void GetSizeInfo(out int numFiles, out long numBytes, out long? bytesFree) { cache.GetSizeInfo(out numFiles, out numBytes, out bytesFree); } @@ -235,7 +235,7 @@ public static bool ZipValid(string filename, long onePercent = new FileInfo(filename).Length / 100; // Perform CRC and other checks if (zip.TestArchive(true, TestStrategy.FindFirstError, - (TestStatus st, string msg) => + (st, msg) => { // This delegate is called as TestArchive proceeds through its // steps, both routine and abnormal. diff --git a/Core/Properties/Resources.resx b/Core/Properties/Resources.resx index cfeb749f4..75c812459 100644 --- a/Core/Properties/Resources.resx +++ b/Core/Properties/Resources.resx @@ -211,6 +211,8 @@ Install the `mono-complete` package or equivalent for your operating system.Auto {0} Please select the game that is installed at {0} Old cache folder contains {0}. New cache folder has {1} free. +What would you like to do? + Old cache folder contains {0}. New cache folder has unknown free space. What would you like to do? Move old cached files to new cache folder Delete cached files diff --git a/Core/Repositories/AvailableModule.cs b/Core/Repositories/AvailableModule.cs index c9e14ea08..729661f93 100644 --- a/Core/Repositories/AvailableModule.cs +++ b/Core/Repositories/AvailableModule.cs @@ -215,8 +215,7 @@ public GameVersion LatestCompatibleGameVersion(List realVersions) // Can't get later than Any, so no need for more complex logic return realVersions?.LastOrDefault() // This is needed for when we have no real versions loaded, such as tests - ?? module_version.Values.Select(m => m.LatestCompatibleGameVersion()) - .Max() + ?? module_version.Values.Max(m => m.LatestCompatibleGameVersion()) ?? module_version.Values.Last().LatestCompatibleGameVersion(); } // Find the range with the highest upper bound @@ -226,8 +225,7 @@ public GameVersion LatestCompatibleGameVersion(List realVersions) : best); return realVersions?.LastOrDefault(bestRange.Contains) // This is needed for when we have no real versions loaded, such as tests - ?? module_version.Values.Select(m => m.LatestCompatibleGameVersion()) - .Max() + ?? module_version.Values.Max(m => m.LatestCompatibleGameVersion()) ?? module_version.Values.Last().LatestCompatibleGameVersion(); } diff --git a/Core/Utilities.cs b/Core/Utilities.cs index c0db6e563..dd091fb3d 100644 --- a/Core/Utilities.cs +++ b/Core/Utilities.cs @@ -142,7 +142,7 @@ private static void CopyDirectory(string sourceDirPath, // Select only paths within subdir, prune prefixes private static IEnumerable SubPaths(string parent, string[] paths) => paths.Where(p => p.StartsWith($"{parent}/", Platform.PathComparison)) - .Select(p => p.Remove(0, parent.Length + 1)); + .Select(p => p[(parent.Length + 1)..]); /// /// Launch a URL. For YEARS this was done by Process.Start in a diff --git a/GUI/Dialogs/SettingsDialog.cs b/GUI/Dialogs/SettingsDialog.cs index 9f15923a9..1d0c73b2b 100644 --- a/GUI/Dialogs/SettingsDialog.cs +++ b/GUI/Dialogs/SettingsDialog.cs @@ -105,9 +105,9 @@ private void UpdateCacheInfo(string newPath) { try { - manager.Cache.GetSizeInfo(out int cacheFileCount, - out long cacheSize, - out long cacheFreeSpace); + manager.Cache.GetSizeInfo(out int cacheFileCount, + out long cacheSize, + out long? cacheFreeSpace); Util.Invoke(this, () => { @@ -116,10 +116,14 @@ private void UpdateCacheInfo(string newPath) // Show setting in MiB CacheLimit.Text = (coreConfig.CacheSizeLimit.Value / 1024 / 1024).ToString(); } - CacheSummary.Text = string.Format(Properties.Resources.SettingsDialogSummmary, - cacheFileCount, - CkanModule.FmtSize(cacheSize), - CkanModule.FmtSize(cacheFreeSpace)); + CacheSummary.Text = cacheFreeSpace.HasValue + ? string.Format(Properties.Resources.SettingsDialogSummmary, + cacheFileCount, + CkanModule.FmtSize(cacheSize), + CkanModule.FmtSize(cacheFreeSpace.Value)) + : string.Format(Properties.Resources.SettingsDialogSummmaryFreeSpaceUnknown, + cacheFileCount, + CkanModule.FmtSize(cacheSize)); CacheSummary.ForeColor = SystemColors.ControlText; OpenCacheButton.Enabled = true; ClearCacheButton.Enabled = (cacheSize > 0); diff --git a/GUI/Main/MainImport.cs b/GUI/Main/MainImport.cs index f19dda1e2..1e59b86a3 100644 --- a/GUI/Main/MainImport.cs +++ b/GUI/Main/MainImport.cs @@ -47,7 +47,7 @@ private void ImportModules() e.Result = ModuleInstaller.ImportFiles( GetFiles(dlg.FileNames), currentUser, - (CkanModule mod) => + mod => { if (ManageMods.mainModList .full_list_of_mod_rows diff --git a/GUI/Main/MainRepo.cs b/GUI/Main/MainRepo.cs index 5d49a14bf..e3023ee93 100644 --- a/GUI/Main/MainRepo.cs +++ b/GUI/Main/MainRepo.cs @@ -97,8 +97,7 @@ private void UpdateRepo(object? sender, DoWorkEventArgs? e) var downloader = new NetAsyncDownloader(currentUser, () => null, userAgent); downloader.TargetProgress += (target, remaining, total) => { - var repo = repos.Where(r => target.urls.Contains(r.uri)) - .FirstOrDefault(); + var repo = repos.FirstOrDefault(r => target.urls.Contains(r.uri)); if (repo != null && total > 0) { Wait.SetProgress(repo.name, remaining, total); diff --git a/GUI/Model/ModList.cs b/GUI/Model/ModList.cs index 1ec5328c9..ef6e055ea 100644 --- a/GUI/Model/ModList.cs +++ b/GUI/Model/ModList.cs @@ -309,7 +309,7 @@ private DataGridViewRow MakeRow(GUIMod mod, List? changes, string? in item.DefaultCellStyle.BackColor = GetRowBackground(mod, false, instanceName, game); item.DefaultCellStyle.SelectionBackColor = SelectionBlend(item.DefaultCellStyle.BackColor); - var myChange = changes?.FindLast((ModChange ch) => ch.Mod.Equals(mod)); + var myChange = changes?.FindLast(ch => ch.Mod.Equals(mod)); var selecting = mod.IsAutodetected ? new DataGridViewTextBoxCell() diff --git a/GUI/Properties/Resources.resx b/GUI/Properties/Resources.resx index a2802e6bb..4e068c919 100644 --- a/GUI/Properties/Resources.resx +++ b/GUI/Properties/Resources.resx @@ -371,6 +371,7 @@ Find the folder where your game is installed and choose one of these files: Browse the cache folder Delete files from the cache {0} files, {1}, {2} free + {0} files, {1}, free space unknown Invalid path: {0} Choose a folder for storing CKAN's mod downloads: Do you really want to delete {0} cached files, freeing {1}? diff --git a/GUI/Util.cs b/GUI/Util.cs index 09b94ea5e..05d23f001 100644 --- a/GUI/Util.cs +++ b/GUI/Util.cs @@ -272,7 +272,7 @@ public static EventHandler Debounce( doneFunc(receivedFrom, received); }; - return (object? sender, EventT evt) => + return (sender, evt) => { if (!abortFunc(sender, evt)) { diff --git a/Netkan/Transformers/InstallSizeTransformer.cs b/Netkan/Transformers/InstallSizeTransformer.cs index 8616575d7..1a995ffb3 100644 --- a/Netkan/Transformers/InstallSizeTransformer.cs +++ b/Netkan/Transformers/InstallSizeTransformer.cs @@ -29,8 +29,7 @@ public IEnumerable Transform(Metadata metadata, TransformOptions? opts ZipFile zip = new ZipFile(_http.DownloadModule(metadata)); GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser()); json["install_size"] = _moduleService.FileSources(mod, zip, inst) - .Select(ze => ze.Size) - .Sum(); + .Sum(ze => ze.Size); yield return new Metadata(json); } else