Skip to content

Commit 37ea41d

Browse files
committed
Merge branch 'dev'
* dev: make upgrade window wider install apk: display error message if failed add disable unity hub from launching on Editor start #95 add setting for using unoffical releases list adding unofficial releases watchlist downloads
2 parents b105fca + efb21fb commit 37ea41d

File tree

8 files changed

+521
-31
lines changed

8 files changed

+521
-31
lines changed

UnityLauncherPro/Data/UnityVersion.cs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public class UnityVersion
88
public string Version { get; set; }
99
public UnityVersionStream Stream { get; set; }
1010
public DateTime ReleaseDate { get; set; }
11+
public string directURL { get; set; } = null; // if found from unofficial releases list
1112

1213
public static UnityVersion FromJson(string json)
1314
{

UnityLauncherPro/GetUnityUpdates.cs

+126-2
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,31 @@ public static class GetUnityUpdates
1717
private const string CacheFileName = "UnityVersionCache.json";
1818
private static readonly HttpClient Client = new HttpClient();
1919

20-
public static async Task<List<UnityVersion>> FetchAll()
20+
static Dictionary<string, string> unofficialReleaseURLs = new Dictionary<string, string>();
21+
22+
public static async Task<List<UnityVersion>> FetchAll(bool useUnofficialList = false)
2123
{
2224
var cachedVersions = LoadCachedVersions();
2325
var newVersions = await FetchNewVersions(cachedVersions);
2426

2527
var allVersions = newVersions.Concat(cachedVersions).ToList();
2628

29+
if (useUnofficialList == true)
30+
{
31+
var unofficialVersions = await FetchUnofficialVersions(cachedVersions);
32+
unofficialReleaseURLs.Clear();
33+
// TODO modify FetchUnofficialVersions to put items in this dictionary directlys
34+
foreach (var version in unofficialVersions)
35+
{
36+
//Console.WriteLine("unofficial: " + version.Version + " , " + version.directURL);
37+
if (unofficialReleaseURLs.ContainsKey(version.Version) == false)
38+
{
39+
unofficialReleaseURLs.Add(version.Version, version.directURL);
40+
}
41+
}
42+
allVersions = unofficialVersions.Concat(allVersions).ToList();
43+
}
44+
2745
if (newVersions.Count > 0)
2846
{
2947
SaveCachedVersions(allVersions);
@@ -32,13 +50,89 @@ public static async Task<List<UnityVersion>> FetchAll()
3250
return allVersions;
3351
}
3452

53+
public static async Task<List<UnityVersion>> FetchUnofficialVersions(List<UnityVersion> cachedVersions)
54+
{
55+
var unofficialVersions = new List<UnityVersion>();
56+
var existingVersions = new HashSet<string>(cachedVersions.Select(v => v.Version));
57+
58+
try
59+
{
60+
string url = "https://raw.githubusercontent.com/unitycoder/UnofficialUnityReleasesWatcher/refs/heads/main/unity-releases.md";
61+
62+
var content = await Client.GetStringAsync(url);
63+
64+
// Parse the Markdown content
65+
var lines = content.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
66+
foreach (var line in lines)
67+
{
68+
if (line.StartsWith("- ")) // Identify Markdown list items
69+
{
70+
var urlPart = line.Substring(2).Trim();
71+
var version = ExtractVersionFromUrl(urlPart);
72+
73+
if (!string.IsNullOrEmpty(version) && !existingVersions.Contains(version))
74+
{
75+
var stream = InferStreamFromVersion(version);
76+
77+
unofficialVersions.Add(new UnityVersion
78+
{
79+
Version = version,
80+
Stream = stream,
81+
ReleaseDate = DateTime.Now, // NOTE not correct, but we don't have known release date for unofficial versions (its only when they are found..)
82+
//ReleaseDate = DateTime.MinValue // Release date is unavailable in the MD format, TODO add to md as #2021-01-01 ?
83+
directURL = urlPart, // this is available only for unofficial releases
84+
});
85+
}
86+
}
87+
}
88+
}
89+
catch (Exception ex)
90+
{
91+
Console.WriteLine($"Error fetching unofficial versions: {ex.Message}");
92+
}
93+
94+
return unofficialVersions;
95+
}
96+
97+
// TODO fixme, f is not always LTS
98+
private static UnityVersionStream InferStreamFromVersion(string version)
99+
{
100+
if (Tools.IsAlpha(version)) return UnityVersionStream.Alpha;
101+
if (Tools.IsBeta(version)) return UnityVersionStream.Beta;
102+
if (Tools.IsLTS(version)) return UnityVersionStream.LTS;
103+
104+
//if (version.Contains("a")) return UnityVersionStream.Alpha;
105+
//if (version.Contains("b")) return UnityVersionStream.Beta;
106+
//if (version.Contains("f")) return UnityVersionStream.LTS;
107+
return UnityVersionStream.Tech; // Default to Tech if no identifier is found
108+
}
109+
110+
/// <summary>
111+
/// Extracts the Unity version from the given URL.
112+
/// </summary>
113+
/// <param name="url">The URL to parse.</param>
114+
/// <returns>The Unity version string.</returns>
115+
private static string ExtractVersionFromUrl(string url)
116+
{
117+
try
118+
{
119+
var versionStart = url.LastIndexOf('#') + 1;
120+
return versionStart > 0 && versionStart < url.Length ? url.Substring(versionStart) : null;
121+
}
122+
catch
123+
{
124+
return null;
125+
}
126+
}
127+
35128
public static async Task<string> FetchDownloadUrl(string unityVersion)
36129
{
37130
if (string.IsNullOrEmpty(unityVersion))
38131
{
39132
return null;
40133
}
41134

135+
// unity release api
42136
string apiUrl = $"{BaseApiUrl}?limit=1&version={unityVersion}&architecture=X86_64&platform=WINDOWS";
43137

44138
try
@@ -53,8 +147,37 @@ public static async Task<string> FetchDownloadUrl(string unityVersion)
53147
}
54148
}
55149

150+
static string ParseHashCodeFromURL(string url)
151+
{
152+
// https://beta.unity3d.com/download/330fbefc18b7/download.html#6000.1.0a8 > 330fbefc18b7
153+
154+
int hashStart = url.IndexOf("download/") + 9;
155+
int hashEnd = url.IndexOf("/download.html", hashStart);
156+
return url.Substring(hashStart, hashEnd - hashStart);
157+
}
158+
56159
private static async Task<string> ExtractDownloadUrlAsync(string json, string unityVersion)
57160
{
161+
//Console.WriteLine("json: " + json + " vers: " + unityVersion);
162+
163+
if (json.Contains("\"results\":[]"))
164+
{
165+
Console.WriteLine("No results found from releases API, checking unofficial list (if enabled)");
166+
167+
if (unofficialReleaseURLs.ContainsKey(unityVersion))
168+
{
169+
Console.WriteLine("Unofficial release found in the list.");
170+
171+
string unityHash = ParseHashCodeFromURL(unofficialReleaseURLs[unityVersion]);
172+
// Console.WriteLine(unityHash);
173+
string downloadURL = Tools.ParseDownloadURLFromWebpage(unityVersion, unityHash, false, true);
174+
// Console.WriteLine("direct download url: "+downloadURL);
175+
return downloadURL;
176+
}
177+
178+
return null;
179+
}
180+
58181
int resultsIndex = json.IndexOf("\"results\":");
59182
if (resultsIndex == -1) return null;
60183

@@ -84,7 +207,7 @@ private static async Task<string> ExtractDownloadUrlAsync(string json, string un
84207

85208
if (await CheckAssistantUrl(assistantUrl))
86209
{
87-
Console.WriteLine("Assistant download URL found.");
210+
//Console.WriteLine("ExtractDownloadUrlAsync: Assistant download URL found.");
88211
return assistantUrl;
89212
}
90213
else
@@ -279,6 +402,7 @@ private static void SaveCachedVersions(List<UnityVersion> versions)
279402
if (configDirectory == null) return;
280403

281404
string cacheFilePath = Path.Combine(configDirectory, CacheFileName);
405+
//Console.WriteLine("Saving cachedrelease: " + cacheFilePath);
282406
File.WriteAllText(cacheFilePath, json);
283407
}
284408
}

UnityLauncherPro/MainWindow.xaml

+2
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,8 @@
810810
<CheckBox x:Name="chkQuitAfterCommandline" Content="Close after launching from Explorer" Unchecked="ChkQuitAfterCommandline_CheckedChanged" Checked="ChkQuitAfterCommandline_CheckedChanged" ToolTip="Close launcher after running from commandline or Explorer (recommended)" HorizontalAlignment="Left"/>
811811
<CheckBox x:Name="chkAllowSingleInstanceOnly" Content="Allow single instance only" Checked="ChkAllowSingleInstanceOnly_CheckedChanged" Unchecked="ChkAllowSingleInstanceOnly_CheckedChanged" ToolTip="Activates already running instance, instead of starting new exe (not working if app is minized to taskbar)" HorizontalAlignment="Left"/>
812812
<CheckBox x:Name="useAlphaReleaseNotesSite" Content="Use Unity Alpha Release Notes Site (only for final versions) " ToolTip="Use the superior (but alpha) Unity Release Notes (https://alpha.release-notes.ds.unity3d.com/) site when clicking on the ReleaseNotes button. Otherwise will default to the normal build page." Checked="UseAlphaReleaseNotes_Checked" Unchecked="UseAlphaReleaseNotes_Checked"/>
813+
<CheckBox x:Name="useUnofficialReleaseList" Content="Use Unofficial Release Watch List (for latest downloads)" ToolTip="Checks latest releases from https://github.com/unitycoder/UnofficialUnityReleasesWatcher (if not yet available in The Unity Releases API)" Checked="useUnofficialReleaseList_Checked" Unchecked="useUnofficialReleaseList_Checked"/>
814+
<CheckBox x:Name="chkDisableUnityHubLaunch" Content="Disable UnityHub launch at Editor start" ToolTip="Overrides UnityHub IPC port. Note: You will be logged out in Editor!" Checked="chkDisableUnityHubLaunch_Checked" Unchecked="chkDisableUnityHubLaunch_Checked"/>
813815
<CheckBox x:Name="chkStreamerMode" Content="Streamer Mode (hide project names and folders)" ToolTip="Hide project names and folders in main view" Checked="ChkStreamerMode_Checked" Unchecked="ChkStreamerMode_Checked" HorizontalAlignment="Left"/>
814816
<!--<StackPanel Orientation="Horizontal" Margin="0,0,0,4">
815817
<TextBox x:Name="txtTemplatePackagesFolder" BorderBrush="Transparent" CaretBrush="{DynamicResource ThemeSearchCaret}" Background="{DynamicResource ThemeTextBoxBackground}" SelectionBrush="{DynamicResource ThemeSearchSelection}" Foreground="{DynamicResource ThemeSearchForeground}" ToolTip="Folder for your custom unitypackage templates (for new project)" Padding="0,3,0,0" Width="110" TextChanged="TxtTemplatePackagesFolder_TextChanged" />

0 commit comments

Comments
 (0)