Skip to content

Commit b3c29fe

Browse files
committed
fix: resolve update & extraction issues, improve visuals
1 parent 8e3f8ca commit b3c29fe

File tree

10 files changed

+492
-187
lines changed

10 files changed

+492
-187
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Compiled output
22
**/bin
33
**/obj
4-
app.manifest
54
*.dll
65
*.pdb
76
*.user

NewModLauncher/MainWindow.axaml.cs

Lines changed: 301 additions & 132 deletions
Large diffs are not rendered by default.

NewModLauncher/Services/ModUpdateService.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ public ModUpdateService(SettingsService settings)
1818

1919
public async Task<bool> IsModUpdateAvailableAsync()
2020
{
21-
var current = _settings.ModVersion;
21+
var current = _settings.ModVersion;
2222
if (string.IsNullOrEmpty(current))
2323
return false;
24-
var latest =(await FetchLatestModVersionAsync())?.TrimStart('v', 'V').Trim();
25-
if (string.IsNullOrEmpty(latest))
24+
var latest = (await FetchLatestModVersionAsync())?.TrimStart('v', 'V').Trim();
25+
if (string.IsNullOrEmpty(latest))
2626
return false;
2727
return VersionUtils.Compare(latest, current) > 0;
2828
}
@@ -43,32 +43,33 @@ public async Task<string> FetchLatestModVersionAsync()
4343
client.DefaultRequestHeaders.Add("User-Agent", "NewModLauncher");
4444
var json = await client.GetStringAsync(ModReleasesUrl);
4545
using var document = JsonDocument.Parse(json);
46-
46+
4747
string zipUrl = "";
4848
string dllUrl = "";
49-
49+
5050
if (document.RootElement.TryGetProperty("assets", out var assets))
5151
{
5252
foreach (var asset in assets.EnumerateArray())
5353
{
54-
if (asset.TryGetProperty("name", out var nameElement) &&
54+
if (asset.TryGetProperty("name", out var nameElement) &&
5555
asset.TryGetProperty("browser_download_url", out var urlElement))
5656
{
5757
string name = nameElement.GetString() ?? "";
5858
string url = urlElement.GetString() ?? "";
59-
60-
if (name.Contains("NewMod") || name.Contains("NewMod-Ms") && name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
59+
60+
if ((name.Contains("NewMod") || name.Contains("NewMod-MS")) && name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
6161
{
6262
zipUrl = url;
6363
}
6464
else if (name.Equals("NewMod.dll", StringComparison.OrdinalIgnoreCase))
6565
{
6666
dllUrl = url;
67+
Logger.Log("MESSAGE", $"{dllUrl}");
6768
}
6869
}
6970
}
7071
}
71-
72+
7273
return (!string.IsNullOrEmpty(zipUrl), zipUrl, dllUrl);
7374
}
7475
}

NewModLauncher/Services/SettingsService.cs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,66 +89,66 @@ public string? AmongUsPath
8989

9090
public string? GameVersion
9191
{
92-
get => _cachedConfig["GameVersion"]?.GetValue<string>();
92+
get => _cachedConfig[nameof(GameVersion)]?.GetValue<string>();
9393
set
9494
{
95-
_cachedConfig["GameVersion"] = value;
95+
_cachedConfig[nameof(GameVersion)] = value;
9696
Save();
9797
}
9898
}
9999

100100
public string LauncherVersion
101101
{
102-
get => _cachedConfig["LauncherVersion"]?.GetValue<string>() ?? "1.0.0";
102+
get => _cachedConfig[nameof(LauncherVersion)]?.GetValue<string>() ?? "1.0.0";
103103
set
104104
{
105-
_cachedConfig["LauncherVersion"] = value;
105+
_cachedConfig[nameof(LauncherVersion)] = value;
106106
Save();
107107
}
108108
}
109109

110110
public string ModVersion
111111
{
112-
get => _cachedConfig["ModVersion"]?.GetValue<string>() ?? "";
112+
get => _cachedConfig[nameof(ModVersion)]?.GetValue<string>() ?? "";
113113
set
114114
{
115-
_cachedConfig["ModVersion"] = value;
115+
_cachedConfig[nameof(ModVersion)] = value;
116116
Save();
117117
}
118118
}
119119
public string GradientType
120120
{
121-
get => _cachedConfig["GradientType"]?.GetValue<string>() ?? "None";
121+
get => _cachedConfig[nameof(GradientType)]?.GetValue<string>() ?? "None";
122122
set
123123
{
124-
_cachedConfig["GradientType"] = value;
124+
_cachedConfig[nameof(GradientType)] = value;
125125
Save();
126126
}
127127
}
128128
public string GradientStartColor
129129
{
130-
get => _cachedConfig["GradientStartColor"]?.GetValue<string>() ?? "#FF000000";
130+
get => _cachedConfig[nameof(GradientStartColor)]?.GetValue<string>() ?? "#FF000000";
131131
set
132132
{
133-
_cachedConfig["GradientStartColor"] = value;
133+
_cachedConfig[nameof(GradientStartColor)] = value;
134134
Save();
135135
}
136136
}
137137
public string GradientEndColor
138138
{
139-
get => _cachedConfig["GradientEndColor"]?.GetValue<string>() ?? "#FF000000";
139+
get => _cachedConfig[nameof(GradientEndColor)]?.GetValue<string>() ?? "#FF000000";
140140
set
141141
{
142-
_cachedConfig["GradientEndColor"] = value;
142+
_cachedConfig[nameof(GradientEndColor)] = value;
143143
Save();
144144
}
145145
}
146146
public bool NightlyBuildsEnabled
147147
{
148-
get => _cachedConfig["NightlyBuildsEnabled"]?.GetValue<bool>() ?? false;
148+
get => _cachedConfig[nameof(NightlyBuildsEnabled)]?.GetValue<bool>() ?? false;
149149
set
150150
{
151-
_cachedConfig["NightlyBuildsEnabled"] = value;
151+
_cachedConfig[nameof(NightlyBuildsEnabled)] = value;
152152
Save();
153153
}
154154
}
@@ -158,7 +158,7 @@ public string[] InstalledMods
158158
{
159159
try
160160
{
161-
var modsArray = _cachedConfig["InstalledMods"]?.AsArray();
161+
var modsArray = _cachedConfig[nameof(InstalledMods)]?.AsArray();
162162
if (modsArray != null)
163163
{
164164
string[] mods = new string[modsArray.Count];
@@ -180,17 +180,17 @@ public string[] InstalledMods
180180
{
181181
array.Add(mod);
182182
}
183-
_cachedConfig["InstalledMods"] = array;
183+
_cachedConfig[nameof(InstalledMods)] = array;
184184
Save();
185185
}
186186
}
187187

188188
public bool AnimationsEnabled
189189
{
190-
get => _cachedConfig["AnimationsEnabled"]?.GetValue<bool>() ?? true;
190+
get => _cachedConfig[nameof(AnimationsEnabled)]?.GetValue<bool>() ?? true;
191191
set
192192
{
193-
_cachedConfig["AnimationsEnabled"] = value;
193+
_cachedConfig[nameof(AnimationsEnabled)] = value;
194194
Save();
195195
}
196196
}

NewModLauncher/ViewModels/ModViewModel.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@ public class ModViewModel : INotifyPropertyChanged
1717
public string Description { get; set; } = "";
1818
public string DownloadUrl { get; set; } = "";
1919
public string RepositoryUrl { get; set; } = "";
20-
public string SupportVersion { get; set; } = "";
2120
public string IconUrl { get; set; } = "";
2221
public string IconText { get; set; } = "";
2322

24-
2523
private bool _isInstalled;
2624
public bool IsInstalled
2725
{
@@ -38,6 +36,22 @@ public bool IsInstalled
3836
}
3937
}
4038

39+
40+
private string _supportVersion = "";
41+
public string SupportVersion
42+
{
43+
get => _supportVersion;
44+
set
45+
{
46+
if (_supportVersion != value)
47+
{
48+
_supportVersion = value;
49+
OnPropertyChanged();
50+
OnPropertyChanged(nameof(IsCompatible));
51+
}
52+
}
53+
}
54+
4155
private bool _isCompatible;
4256
public bool IsCompatible
4357
{

NewModLauncher/ViewModels/ModsViewModel.cs

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
using System.Linq;
55
using System.Threading.Tasks;
66
using System.Net.Http;
7+
using System.Text.Json;
78

89
namespace NewModLauncher.ViewModels
910
{
1011
public class ModsViewModel : INotifyPropertyChanged
1112
{
1213
public ObservableCollection<ModViewModel> Mods { get; } = new();
14+
public bool _isRefreshing;
15+
public bool IsRefreshing { get => _isRefreshing; private set { _isRefreshing = value; OnPropertyChanged(); OnPropertyChanged(nameof(RefreshText)); } }
16+
public string RefreshText => IsRefreshing ? "Refreshing mods…" : "";
1317
private string _currentGameVersion = "";
1418
public string CurrentGameVersion
1519
{
@@ -30,7 +34,6 @@ public ModsViewModel()
3034
{
3135
Name = "yanplaRoles",
3236
IconText = "YR",
33-
Version = "v0.1.8",
3437
Description = "yanplaRoles is a mod for the game Among Us that introduces new roles and modifiers.",
3538
DownloadUrl = "https://github.com/yanpla/yanplaRoles/releases/latest/download/yanplaRoles.dll",
3639
RepositoryUrl = "https://github.com/yanpla/yanplaRoles",
@@ -40,7 +43,6 @@ public ModsViewModel()
4043
{
4144
Name = "Submerged",
4245
IconUrl = "https://raw.githubusercontent.com/SubmergedAmongUs/Submerged/main/Submerged/Resources/Images/OptionsIcon.png",
43-
Version = "v2025.1.30",
4446
Description = "Submerged is a mod for Among Us which adds a new map into the game.",
4547
DownloadUrl = "https://github.com/SubmergedAmongUs/Submerged/releases/latest/download/Submerged.dll",
4648
RepositoryUrl = "https://github.com/SubmergedAmongUs/Submerged",
@@ -50,11 +52,10 @@ public ModsViewModel()
5052
{
5153
Name = "Launchpad Reloaded",
5254
IconUrl = "https://allofus.dev/static/images/launchpad_no_shadow.png",
53-
Version = "v0.3.4",
5455
Description = "A vanilla oriented fun and unique Among Us client mod.",
55-
DownloadUrl = "https://github.com/All-Of-Us-Mods/LaunchpadReloaded/releases/download/0.3.4/LaunchpadReloaded.dll",
56+
DownloadUrl = "https://github.com/All-Of-Us-Mods/LaunchpadReloaded/releases/download/latest/LaunchpadReloaded.dll",
5657
RepositoryUrl = "https://github.com/All-Of-Us-Mods/LaunchpadReloaded",
57-
SupportVersion = "2025.4.15"
58+
SupportVersion = "2025.6.10"
5859
});
5960

6061
foreach (var mod in Mods)
@@ -72,31 +73,66 @@ public void CheckModInstallStates(string[] installedMods)
7273
public void UpdateModCompatibility()
7374
{
7475
foreach (var mod in Mods)
75-
mod.IsCompatible = VersionUtils.Compare(CurrentGameVersion, mod.SupportVersion) >= 0;
76+
mod.IsCompatible = VersionUtils.Compare(CurrentGameVersion, mod.SupportVersion) <= 0;
7677
}
7778
public async Task CheckForModUpdatesAsync()
7879
{
79-
foreach (var mod in Mods)
80+
IsRefreshing = true;
81+
try
8082
{
81-
mod.LatestVersion = await GetLatestVersionFromGithub(mod.RepositoryUrl);
82-
mod.NotifyUpdateChange();
83-
};
84-
}
83+
foreach (var mod in Mods)
84+
{
85+
var info = await GetLatestReleaseInfo(mod.RepositoryUrl);
86+
if (info != null)
87+
{
88+
if (!string.IsNullOrWhiteSpace(info.Tag))
89+
mod.Version = info.Tag;
90+
91+
if (string.IsNullOrWhiteSpace(mod.DownloadUrl) && !string.IsNullOrWhiteSpace(info.DllAssetUrl))
92+
mod.DownloadUrl = info.DllAssetUrl;
8593

86-
private async Task<string> GetLatestVersionFromGithub(string repoUrl)
94+
mod.NotifyUpdateChange();
95+
}
96+
}
97+
}
98+
finally { IsRefreshing = false; }
99+
}
100+
private async Task<ReleaseInfo> GetLatestReleaseInfo(string repoUrl)
87101
{
88-
try
102+
var userRepo = repoUrl.Replace("https://github.com/", "").TrimEnd('/');
103+
var apiUrl = $"https://api.github.com/repos/{userRepo}/releases/latest";
104+
105+
using var client = new HttpClient();
106+
client.DefaultRequestHeaders.Add("User-Agent", "NewModLauncher");
107+
108+
var json = await client.GetStringAsync(apiUrl);
109+
using var doc = JsonDocument.Parse(json);
110+
111+
var root = doc.RootElement;
112+
string tag = root.TryGetProperty("tag_name", out var tagProp) ? tagProp.GetString() ?? "" : "";
113+
114+
string dllUrl = "";
115+
if (root.TryGetProperty("assets", out var assets) && assets.ValueKind == JsonValueKind.Array)
89116
{
90-
var userRepo = repoUrl.Replace("https://github.com/", "").TrimEnd('/');
91-
var apiUrl = $"https://api.github.com/repos/{userRepo}/releases/latest";
92-
using var client = new HttpClient();
93-
client.DefaultRequestHeaders.Add("User-Agent", "NewModLauncher");
94-
var json = await client.GetStringAsync(apiUrl);
95-
using var doc = System.Text.Json.JsonDocument.Parse(json);
96-
var tag = doc.RootElement.GetProperty("tag_name").GetString() ?? "";
97-
return tag;
98-
} catch {}
99-
return "";
117+
dllUrl = assets.EnumerateArray()
118+
.Select(a => new
119+
{
120+
Name = a.TryGetProperty("name", out var n) ? n.GetString() ?? "" : "",
121+
Url = a.TryGetProperty("browser_download_url", out var u) ? u.GetString() ?? "" : ""
122+
})
123+
.Where(x => x.Name.EndsWith(".dll", System.StringComparison.OrdinalIgnoreCase))
124+
.OrderByDescending(x => x.Name.Length)
125+
.Select(x => x.Url)
126+
.FirstOrDefault() ?? "";
127+
}
128+
129+
return new ReleaseInfo { Tag = tag, DllAssetUrl = dllUrl };
130+
}
131+
132+
public sealed class ReleaseInfo
133+
{
134+
public string Tag { get; init; } = "";
135+
public string DllAssetUrl { get; init; } = "";
100136
}
101137

102138
public event PropertyChangedEventHandler? PropertyChanged;

NewModLauncher/Views/ModsView.axaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@
1919
FontSize="18"
2020
FontWeight="SemiBold"
2121
Foreground="White" />
22+
<Button x:Name="RefreshButton"
23+
Grid.Column="1"
24+
Content="Refresh"
25+
Classes="secondary"
26+
Click="OnRefreshModClick"/>
2227

2328
<TextBlock Text="These mods are compatible with NewMod and can be used together."
2429
Foreground="#B0B0B0"
2530
TextWrapping="Wrap"
2631
Margin="0,0,0,10" />
27-
32+
2833
<!-- Dynamic Mods List -->
2934
<ItemsControl Name="ModsItemsControl" ItemsSource="{Binding Mods}">
3035
<ItemsControl.ItemTemplate>

0 commit comments

Comments
 (0)