Skip to content

Commit fc43d8e

Browse files
committed
adding unity templates loading: fetch templates for selected unity version #147
1 parent dc8a1bd commit fc43d8e

File tree

1 file changed

+81
-38
lines changed

1 file changed

+81
-38
lines changed

UnityLauncherPro/NewProject.xaml.cs

Lines changed: 81 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.IO;
44
using System.Net.Http;
55
using System.Text;
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using System.Windows;
79
using System.Windows.Controls;
810
using System.Windows.Input;
@@ -27,6 +29,7 @@ public partial class NewProject : Window
2729
int previousSelectedModuleIndex = -1;
2830

2931
public static string targetFolder { get; private set; } = null;
32+
private CancellationTokenSource _templateLoadCancellation;
3033

3134
public NewProject(string unityVersion, string suggestedName, string targetFolder, bool nameIsLocked = false)
3235
{
@@ -35,9 +38,6 @@ public NewProject(string unityVersion, string suggestedName, string targetFolder
3538

3639
NewProject.targetFolder = targetFolder;
3740

38-
// TODO could optionally disable templates in settings
39-
_ = LoadOnlineTemplatesAsync();
40-
4141
LoadSettings();
4242

4343
// get version
@@ -65,6 +65,9 @@ public NewProject(string unityVersion, string suggestedName, string targetFolder
6565
{
6666
gridAvailableVersions.SelectedIndex = i;
6767
gridAvailableVersions.ScrollIntoView(gridAvailableVersions.SelectedItem);
68+
69+
string baseVersion = GetBaseVersion(newVersion);
70+
_ = LoadOnlineTemplatesAsync(baseVersion);
6871
break;
6972
}
7073
}
@@ -309,6 +312,23 @@ private void GridAvailableVersions_SelectionChanged(object sender, SelectionChan
309312
lblOverride.Visibility = chkForceDX11.Visibility = is6000 ? Visibility.Visible : Visibility.Collapsed;
310313
//chkForceDX11.IsChecked = chkForceDX11.Visibility == Visibility.Visible ? forceDX11 : false;
311314
forceDX11 = Settings.Default.forceDX11 && is6000;
315+
316+
string baseVersion = GetBaseVersion(k.Version);
317+
// Cancel previous request
318+
_templateLoadCancellation?.Cancel();
319+
_templateLoadCancellation = new CancellationTokenSource();
320+
_ = LoadOnlineTemplatesAsync(baseVersion, _templateLoadCancellation.Token);
321+
}
322+
323+
string GetBaseVersion(string version)
324+
{
325+
// e.g. 2020.3.15f1 -> 2020.3
326+
var parts = version.Split('.');
327+
if (parts.Length >= 2)
328+
{
329+
return parts[0] + "." + parts[1];
330+
}
331+
return version;
312332
}
313333

314334
private void GridAvailableVersions_Loaded(object sender, RoutedEventArgs e)
@@ -418,47 +438,91 @@ private void btnCreateMissingFolder_Click(object sender, RoutedEventArgs e)
418438
}
419439
}
420440

421-
private async System.Threading.Tasks.Task LoadOnlineTemplatesAsync()
441+
private async Task LoadOnlineTemplatesAsync(string baseVersion, CancellationToken cancellationToken = default)
422442
{
423443
try
424444
{
425445
using (var client = new HttpClient())
426446
{
427447
client.DefaultRequestHeaders.Add("Accept", "application/json");
428448

429-
// Build JSON manually
430-
var graphqlJson = "{\"query\":\"fragment TemplateEntity on Template { __typename name packageName description type buildPlatforms renderPipeline previewImage { url } versions { name tarball { url } } } query HUB__getTemplates($limit: Int! $skip: Int! $orderBy: TemplateOrder! $supportedUnityEditorVersions: [String!]!) { getTemplates(limit: $limit skip: $skip orderBy: $orderBy supportedUnityEditorVersions: $supportedUnityEditorVersions) { edges { node { ...TemplateEntity } } } }\",\"variables\":{\"limit\":50,\"skip\":0,\"orderBy\":\"WEIGHTED_DESC\",\"supportedUnityEditorVersions\":[\"6000.0\"]}}";
449+
var graphqlJson = "{\"query\":\"fragment TemplateEntity on Template { __typename name packageName description type buildPlatforms renderPipeline previewImage { url } versions { name tarball { url } } } query HUB__getTemplates($limit: Int! $skip: Int! $orderBy: TemplateOrder! $supportedUnityEditorVersions: [String!]!) { getTemplates(limit: $limit skip: $skip orderBy: $orderBy supportedUnityEditorVersions: $supportedUnityEditorVersions) { edges { node { ...TemplateEntity } } } }\",\"variables\":{\"limit\":40,\"skip\":0,\"orderBy\":\"WEIGHTED_DESC\",\"supportedUnityEditorVersions\":[\"" + baseVersion + "\"]}}";
431450

432451
var content = new StringContent(graphqlJson, Encoding.UTF8, "application/json");
433452

434-
var response = await client.PostAsync("https://live-platform-api.prd.ld.unity3d.com/graphql", content);
453+
// Check for cancellation before making request
454+
if (cancellationToken.IsCancellationRequested) return;
455+
456+
var response = await client.PostAsync("https://live-platform-api.prd.ld.unity3d.com/graphql", content, cancellationToken);
457+
458+
// Check for cancellation after request
459+
if (cancellationToken.IsCancellationRequested) return;
435460

436461
if (response.IsSuccessStatusCode)
437462
{
438463
var responseString = await response.Content.ReadAsStringAsync();
464+
465+
// Check for cancellation before parsing
466+
if (cancellationToken.IsCancellationRequested) return;
467+
439468
var templates = ParseTemplatesFromJson(responseString);
440469

441-
// Update UI on dispatcher thread
442-
Dispatcher.Invoke(() =>
470+
// Update UI on dispatcher thread only if not cancelled
471+
if (!cancellationToken.IsCancellationRequested)
443472
{
444-
listOnlineTemplates.Items.Clear();
445-
listOnlineTemplates.ItemsSource = templates;
446-
});
473+
Dispatcher.Invoke(() =>
474+
{
475+
// Only set ItemsSource, don't touch Items
476+
listOnlineTemplates.ItemsSource = templates;
477+
});
478+
}
447479
}
448480
else
449481
{
450482
Console.WriteLine($"GraphQL request failed: {response.StatusCode}");
451-
LoadFallbackTemplates();
483+
if (!cancellationToken.IsCancellationRequested)
484+
{
485+
LoadFallbackTemplates();
486+
}
452487
}
453488
}
454489
}
490+
catch (OperationCanceledException)
491+
{
492+
// Request was cancelled, this is expected
493+
Console.WriteLine("Template loading cancelled");
494+
}
455495
catch (Exception ex)
456496
{
457-
Console.WriteLine($"Error loading online templates: {ex.Message}");
458-
LoadFallbackTemplates();
497+
if (!cancellationToken.IsCancellationRequested)
498+
{
499+
Console.WriteLine($"Error loading online templates: {ex.Message}");
500+
LoadFallbackTemplates();
501+
}
459502
}
460503
}
461504

505+
private void LoadFallbackTemplates()
506+
{
507+
var templates = new List<OnlineTemplateItem>
508+
{
509+
new OnlineTemplateItem
510+
{
511+
Name = "3D Template",
512+
Description = "A great starting point for 3D projects using the Universal Render Pipeline (URP).",
513+
PreviewImageURL = "pack://application:,,,/Images/icon.png",
514+
Type = "CORE",
515+
RenderPipeline = "URP"
516+
}
517+
};
518+
519+
Dispatcher.Invoke(() =>
520+
{
521+
// Only set ItemsSource, don't use Items.Clear()
522+
listOnlineTemplates.ItemsSource = templates;
523+
});
524+
}
525+
462526
private List<OnlineTemplateItem> ParseTemplatesFromJson(string json)
463527
{
464528
var templates = new List<OnlineTemplateItem>();
@@ -576,26 +640,5 @@ private int FindMatchingBrace(string json, int openBraceIndex)
576640

577641
return -1;
578642
}
579-
580-
private void LoadFallbackTemplates()
581-
{
582-
var templates = new List<OnlineTemplateItem>
583-
{
584-
new OnlineTemplateItem
585-
{
586-
Name = "3D Template",
587-
Description = "A great starting point for 3D projects using the Universal Render Pipeline (URP).",
588-
PreviewImageURL = "pack://application:,,,/Images/icon.png",
589-
Type = "CORE",
590-
RenderPipeline = "URP"
591-
}
592-
};
593-
594-
Dispatcher.Invoke(() =>
595-
{
596-
listOnlineTemplates.Items.Clear();
597-
listOnlineTemplates.ItemsSource = templates;
598-
});
599-
}
600-
}
601-
}
643+
} // class NewProject
644+
} // namespace UnityLauncherPro

0 commit comments

Comments
 (0)