Skip to content

Commit 80e4183

Browse files
committed
Fixed a bug with update mods and added select/deselect all keyboard shortcuts (CTRL + A to select, ESC to deselect)
1 parent f8a41bc commit 80e4183

2 files changed

Lines changed: 181 additions & 54 deletions

File tree

Controls/ModCard.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ public class ModCard : Panel
4747
public bool IsSelected => _chkSelected?.Checked ?? false;
4848
public Mod BoundMod => _mod;
4949

50+
public void UpdateVersion(ModVersion newVersion)
51+
{
52+
if (newVersion != null && _version != newVersion)
53+
{
54+
_version = newVersion;
55+
UpdateUI();
56+
}
57+
}
58+
5059
public void SetInstallButtonEnabled(bool enabled)
5160
{
5261
if (_btnInstall != null)
@@ -725,11 +734,18 @@ public void UpdateUI()
725734
_lblVersion.Visible = true;
726735
}
727736

728-
string versionText = $"Version: {_version.Version}";
729-
if (_version.IsPreRelease)
737+
// For installed mods, prefer mod.InstalledVersion over _version to ensure we show the correct version after updates
738+
ModVersion versionToDisplay = _version;
739+
if ((isInstalled || _isInstalledView) && _mod.InstalledVersion != null)
740+
{
741+
versionToDisplay = _mod.InstalledVersion;
742+
}
743+
744+
string versionText = $"Version: {versionToDisplay.Version}";
745+
if (versionToDisplay.IsPreRelease)
730746
versionText += " (Beta)";
731-
if (!string.IsNullOrEmpty(_version.GameVersion))
732-
versionText += $" ({_version.GameVersion})";
747+
if (!string.IsNullOrEmpty(versionToDisplay.GameVersion))
748+
versionText += $" ({versionToDisplay.GameVersion})";
733749

734750
var versionColor = _palette.SecondaryTextColor;
735751

Main.cs

Lines changed: 161 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ public Main()
9292
tabControl.SelectedIndexChanged += TabControl_SelectedIndexChanged;
9393
}
9494

95+
// Add keyboard shortcut for Select All (Ctrl+A)
96+
this.KeyPreview = true;
97+
this.KeyDown += Main_KeyDown;
98+
9599
// Initialize sidebar and header
96100
UpdateSidebarSelection();
97101
UpdateStats();
@@ -377,6 +381,137 @@ private void TabControl_SelectedIndexChanged(object sender, EventArgs e)
377381
leftSidebar.Controls.SetChildIndex(sidebarBorder, leftSidebar.Controls.Count - 1);
378382
}
379383
}
384+
385+
private void Main_KeyDown(object sender, KeyEventArgs e)
386+
{
387+
// Handle Ctrl+A to select all mods in current tab
388+
// Only handle if not in a text input control
389+
if (e.Control && e.KeyCode == Keys.A)
390+
{
391+
var focusedControl = this.ActiveControl;
392+
bool isTextInput = focusedControl is TextBox ||
393+
focusedControl is RichTextBox ||
394+
focusedControl is ComboBox;
395+
396+
// Only handle Ctrl+A if not in a text input control
397+
if (!isTextInput)
398+
{
399+
e.Handled = true;
400+
e.SuppressKeyPress = true;
401+
SelectAllModsInCurrentTab();
402+
}
403+
}
404+
// Handle ESCAPE to deselect all mods in current tab
405+
else if (e.KeyCode == Keys.Escape)
406+
{
407+
var focusedControl = this.ActiveControl;
408+
bool isTextInput = focusedControl is TextBox ||
409+
focusedControl is RichTextBox ||
410+
focusedControl is ComboBox;
411+
412+
// Only handle ESCAPE if not in a text input control (let ESCAPE close dialogs, clear text, etc.)
413+
if (!isTextInput)
414+
{
415+
e.Handled = true;
416+
e.SuppressKeyPress = true;
417+
DeselectAllModsInCurrentTab();
418+
}
419+
}
420+
}
421+
422+
private void SelectAllModsInCurrentTab()
423+
{
424+
if (tabControl == null)
425+
return;
426+
427+
bool isInstalledView = tabControl.SelectedIndex == 0; // 0 = Installed, 1 = Store
428+
429+
// Get the appropriate panel and selection collection
430+
Panel targetPanel = isInstalledView ? panelInstalled : panelStore;
431+
var bulkSelection = isInstalledView ? _bulkSelectedModIds : _bulkSelectedStoreModIds;
432+
433+
if (targetPanel == null)
434+
return;
435+
436+
// Get all selectable mod cards in the current tab
437+
var selectableCards = targetPanel.Controls.OfType<ModCard>()
438+
.Where(card => card.IsSelectable && card.BoundMod != null)
439+
.ToList();
440+
441+
if (selectableCards.Count == 0)
442+
return;
443+
444+
// Select all cards
445+
foreach (var card in selectableCards)
446+
{
447+
var mod = card.BoundMod;
448+
if (mod == null)
449+
continue;
450+
451+
// Add to bulk selection collection
452+
if (!bulkSelection.Contains(mod.Id))
453+
{
454+
bulkSelection.Add(mod.Id);
455+
}
456+
457+
// Update card UI (suppress event to avoid individual handling)
458+
card.SetSelected(true, true);
459+
}
460+
461+
// Update UI
462+
UpdateBulkActionToolbar(isInstalledView);
463+
if (isInstalledView)
464+
{
465+
UpdateLaunchButtonsState();
466+
}
467+
}
468+
469+
private void DeselectAllModsInCurrentTab()
470+
{
471+
if (tabControl == null)
472+
return;
473+
474+
bool isInstalledView = tabControl.SelectedIndex == 0; // 0 = Installed, 1 = Store
475+
476+
// Get the appropriate panel and selection collections
477+
Panel targetPanel = isInstalledView ? panelInstalled : panelStore;
478+
var bulkSelection = isInstalledView ? _bulkSelectedModIds : _bulkSelectedStoreModIds;
479+
480+
if (targetPanel == null)
481+
return;
482+
483+
// Get all selected mod cards in the current tab
484+
var selectedCards = targetPanel.Controls.OfType<ModCard>()
485+
.Where(card => card.IsSelectable && card.IsSelected && card.BoundMod != null)
486+
.ToList();
487+
488+
// Deselect all cards
489+
foreach (var card in selectedCards)
490+
{
491+
card.SetSelected(false, true);
492+
}
493+
494+
// Clear selection collections
495+
if (isInstalledView)
496+
{
497+
// For installed tab, clear both bulk and launch selections
498+
_bulkSelectedModIds.Clear();
499+
_selectedModIds.Clear();
500+
PersistSelectedMods();
501+
}
502+
else
503+
{
504+
// For store tab, only clear bulk selection
505+
_bulkSelectedStoreModIds.Clear();
506+
}
507+
508+
// Update UI
509+
UpdateBulkActionToolbar(isInstalledView);
510+
if (isInstalledView)
511+
{
512+
UpdateLaunchButtonsState();
513+
}
514+
}
380515

381516
private void UpdateSidebarSelection()
382517
{
@@ -2097,6 +2232,12 @@ private void RefreshModCards()
20972232
{
20982233
// Reuse existing card from installed panel
20992234
installedCard = existingInstalledCard;
2235+
// Update the card's version if it has changed (e.g., after an update)
2236+
if (mod.InstalledVersion != null && installedCard.SelectedVersion != mod.InstalledVersion)
2237+
{
2238+
installedCard.UpdateVersion(mod.InstalledVersion);
2239+
installedCard.CheckForUpdate();
2240+
}
21002241
// Only check for updates if mod was actually installed/uninstalled (not just filtering)
21012242
// Skip CheckForUpdate during filter changes to improve performance
21022243
}
@@ -5113,8 +5254,16 @@ private async Task<bool> FindCompatibleVersionsAsync(List<Mod> mods, List<Versio
51135254

51145255
UpdateStatus("Compatible versions installed. You can now launch the mods.");
51155256

5257+
// Invalidate pending updates cache since mods were updated/downgraded
5258+
_cachedPendingUpdatesCount = null;
5259+
51165260
// Refresh the UI to show updated mod versions
5117-
SafeInvoke(RefreshModCardsDebounced);
5261+
SafeInvoke(() =>
5262+
{
5263+
RefreshModDetectionCache(force: true);
5264+
RefreshModCardsDebounced();
5265+
UpdateStats(); // Explicitly update stats to refresh pending updates count
5266+
});
51185267

51195268
return true;
51205269
}
@@ -6663,58 +6812,12 @@ private async void btnBulkUninstallInstalled_Click(object sender, EventArgs e)
66636812

66646813
private void btnBulkDeselectAllInstalled_Click(object sender, EventArgs e)
66656814
{
6666-
// Clear both bulk and launch selections for installed tab
6667-
var modsToDeselect = _bulkSelectedModIds.Union(_selectedModIds).ToList();
6668-
6669-
foreach (var modId in modsToDeselect)
6670-
{
6671-
if (_modCards.TryGetValue(modId, out var card) && card.IsSelectable)
6672-
{
6673-
card.SetSelected(false, true);
6674-
}
6675-
else
6676-
{
6677-
// Also check panel controls if not in dictionary
6678-
var cardInInstalled = panelInstalled.Controls.OfType<ModCard>()
6679-
.FirstOrDefault(c => c.BoundMod != null &&
6680-
string.Equals(c.BoundMod.Id, modId, StringComparison.OrdinalIgnoreCase));
6681-
if (cardInInstalled != null && cardInInstalled.IsSelectable)
6682-
{
6683-
cardInInstalled.SetSelected(false, true);
6684-
}
6685-
}
6686-
}
6687-
6688-
_bulkSelectedModIds.Clear();
6689-
_selectedModIds.Clear();
6690-
PersistSelectedMods();
6691-
6692-
UpdateBulkActionToolbar(true);
6693-
UpdateLaunchButtonsState();
6815+
DeselectAllModsInCurrentTab();
66946816
}
66956817

66966818
private void btnBulkDeselectAllStore_Click(object sender, EventArgs e)
66976819
{
6698-
foreach (var modId in _bulkSelectedStoreModIds.ToList())
6699-
{
6700-
if (_modCards.TryGetValue(modId, out var card) && card.IsSelectable)
6701-
{
6702-
card.SetSelected(false, true);
6703-
}
6704-
else
6705-
{
6706-
// Also check panel controls if not in dictionary
6707-
var cardInStore = panelStore.Controls.OfType<ModCard>()
6708-
.FirstOrDefault(c => c.BoundMod != null &&
6709-
string.Equals(c.BoundMod.Id, modId, StringComparison.OrdinalIgnoreCase));
6710-
if (cardInStore != null && cardInStore.IsSelectable)
6711-
{
6712-
cardInStore.SetSelected(false, true);
6713-
}
6714-
}
6715-
}
6716-
_bulkSelectedStoreModIds.Clear();
6717-
UpdateBulkActionToolbar(false);
6820+
DeselectAllModsInCurrentTab();
67186821
}
67196822

67206823
private void btnSidebarLaunchVanilla_Click(object sender, EventArgs e)
@@ -7709,7 +7812,15 @@ private async Task UpdateModsAsync(List<Mod> modsToUpdate)
77097812
}
77107813
}
77117814

7712-
SafeInvoke(RefreshModCards);
7815+
// Invalidate pending updates cache since mods were updated
7816+
_cachedPendingUpdatesCount = null;
7817+
7818+
SafeInvoke(() =>
7819+
{
7820+
RefreshModDetectionCache(force: true);
7821+
RefreshModCards();
7822+
UpdateStats(); // Explicitly update stats to refresh pending updates count
7823+
});
77137824

77147825
UpdateStatus("Updates completed!");
77157826
}

0 commit comments

Comments
 (0)