Skip to content

Commit f3374fa

Browse files
committed
Merge branch 'main' into alzollin/cloudApis
2 parents badf9ed + a13ff33 commit f3374fa

34 files changed

+939
-590
lines changed

AIDevGallery/Assets/WinDev.png

230 KB
Loading

AIDevGallery/Controls/SampleContainer.xaml.cs

+13-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using ColorCode;
1111
using Microsoft.UI.Xaml;
1212
using Microsoft.UI.Xaml.Controls;
13+
using Microsoft.Windows.AI;
1314
using System;
1415
using System.Collections.Generic;
1516
using System.Diagnostics.CodeAnalysis;
@@ -180,16 +181,22 @@ public async Task LoadSampleAsync(Sample? sample, List<ModelDetails>? models)
180181

181182
try
182183
{
183-
if (WcrApiHelpers.GetApiAvailability(apiType) != WcrApiAvailability.Available)
184+
var state = WcrApiHelpers.GetApiAvailability(apiType);
185+
if (state != AIFeatureReadyState.Ready && !WcrApiHelpers.IsModelReadyWorkaround.ContainsKey(apiType))
184186
{
185-
modelDownloader.State = WcrApiDownloadState.NotStarted;
186-
modelDownloader.ErrorMessage = string.Empty;
187+
modelDownloader.State = state switch
188+
{
189+
AIFeatureReadyState.EnsureNeeded => WcrApiDownloadState.NotStarted,
190+
_ => WcrApiDownloadState.Error
191+
};
192+
193+
modelDownloader.ErrorMessage = WcrApiHelpers.GetStringDescription(state);
187194
modelDownloader.DownloadProgress = 0;
188195
SampleFrame.Content = null;
189196
_wcrApi = apiType;
190197

191198
VisualStateManager.GoToState(this, "WcrModelNeedsDownload", true);
192-
if (!await modelDownloader.SetDownloadOperation(apiType, sample.Id, WcrApiHelpers.MakeAvailables[apiType]).WaitAsync(token))
199+
if (!await modelDownloader.SetDownloadOperation(apiType, sample.Id, WcrApiHelpers.EnsureReadyFuncs[apiType]).WaitAsync(token))
193200
{
194201
return;
195202
}
@@ -423,9 +430,9 @@ private async void WcrModelDownloader_DownloadClicked(object sender, EventArgs e
423430
return;
424431
}
425432

426-
if (WcrApiHelpers.GetApiAvailability(_wcrApi.Value) != WcrApiAvailability.Available)
433+
if (WcrApiHelpers.GetApiAvailability(_wcrApi.Value) != AIFeatureReadyState.Ready)
427434
{
428-
var op = WcrApiHelpers.MakeAvailables[_wcrApi.Value]();
435+
var op = WcrApiHelpers.EnsureReadyFuncs[_wcrApi.Value]();
429436
if (await modelDownloader.SetDownloadOperation(op))
430437
{
431438
// reload sample

AIDevGallery/Controls/WcrModelDownloader.xaml.cs

+30-11
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
// Licensed under the MIT License.
33

44
using AIDevGallery.Models; // <exclude-line>
5+
using AIDevGallery.Samples;
56
using AIDevGallery.Telemetry.Events; // <exclude-line>
67
using AIDevGallery.Utils; // <exclude-line>
78
using Microsoft.UI.Xaml;
89
using Microsoft.UI.Xaml.Controls;
9-
using Microsoft.Windows.Management.Deployment;
10+
using Microsoft.Windows.AI;
1011
using System;
1112
using System.Linq;
1213
using System.Threading.Tasks;
@@ -17,7 +18,7 @@ namespace AIDevGallery.Controls;
1718
internal sealed partial class WcrModelDownloader : UserControl
1819
{
1920
public event EventHandler? DownloadClicked;
20-
private ModelType modelTypeHint; // <exclude-line>
21+
private ModelType? modelTypeHint; // <exclude-line>
2122
private string sampleId = string.Empty; // <exclude-line>
2223

2324
public int DownloadProgress
@@ -86,19 +87,23 @@ public WcrModelDownloader()
8687
UpdateState();
8788
}
8889

89-
public async Task<bool> SetDownloadOperation(IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress> operation)
90+
public async Task<bool> SetDownloadOperation(IAsyncOperationWithProgress<AIFeatureReadyResult, double> operation)
9091
{
9192
if (operation == null)
9293
{
9394
return false;
9495
}
9596

96-
WcrDownloadOperationTracker.Operations[this.modelTypeHint] = operation; // <exclude-line>
97+
if (modelTypeHint != null)
98+
{
99+
WcrDownloadOperationTracker.Operations[modelTypeHint.Value] = operation; // <exclude-line>
100+
}
101+
97102
operation.Progress = (result, progress) =>
98103
{
99104
DispatcherQueue.TryEnqueue(() =>
100105
{
101-
DownloadProgress = (int)(progress.Progress * 100);
106+
DownloadProgress = (int)(progress * 100);
102107
});
103108
};
104109

@@ -108,32 +113,43 @@ public async Task<bool> SetDownloadOperation(IAsyncOperationWithProgress<Package
108113
{
109114
var result = await operation;
110115

111-
if (result.Status == PackageDeploymentStatus.CompletedSuccess)
116+
if (result.Status == AIFeatureReadyResultState.Success)
112117
{
113118
State = WcrApiDownloadState.Downloaded;
119+
if (modelTypeHint != null)
120+
{
121+
WcrApiHelpers.IsModelReadyWorkaround[modelTypeHint.Value] = true;
122+
}
123+
114124
return true;
115125
}
116126
else
117127
{
118128
State = WcrApiDownloadState.Error;
119129
ErrorMessage = result.ExtendedError.Message;
120-
WcrApiDownloadFailedEvent.Log(this.modelTypeHint, result.ExtendedError.Message); // <exclude-line>
130+
if (modelTypeHint != null)
131+
{
132+
WcrApiDownloadFailedEvent.Log(modelTypeHint.Value, result.ExtendedError.Message); // <exclude-line>
133+
}
121134
}
122135
}
123136
catch (Exception ex)
124137
{
125138
ErrorMessage = ex.Message;
126139
State = WcrApiDownloadState.Error;
127-
WcrApiDownloadFailedEvent.Log(this.modelTypeHint, ex); // <exclude-line>
140+
if (modelTypeHint != null)
141+
{
142+
WcrApiDownloadFailedEvent.Log(modelTypeHint.Value, ex); // <exclude-line>
143+
}
128144
}
129145

130146
return false;
131147
}
132148

133149
// <exclude>
134-
public Task<bool> SetDownloadOperation(ModelType modelType, string sampleId, Func<IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>> makeAvailable)
150+
public Task<bool> SetDownloadOperation(ModelType modelType, string sampleId, Func<IAsyncOperationWithProgress<AIFeatureReadyResult, double>> makeAvailable)
135151
{
136-
IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>? exisitingOperation;
152+
IAsyncOperationWithProgress<AIFeatureReadyResult, double>? exisitingOperation;
137153

138154
WcrDownloadOperationTracker.Operations.TryGetValue(modelType, out exisitingOperation);
139155
this.modelTypeHint = modelType;
@@ -152,7 +168,10 @@ public Task<bool> SetDownloadOperation(ModelType modelType, string sampleId, Fun
152168
private void DownloadModelClicked(object sender, RoutedEventArgs e)
153169
{
154170
DownloadClicked?.Invoke(this, EventArgs.Empty);
155-
WcrApiDownloadRequestedEvent.Log(modelTypeHint, sampleId); // <exclude-line>
171+
if (modelTypeHint != null && sampleId != string.Empty)
172+
{
173+
WcrApiDownloadRequestedEvent.Log(modelTypeHint.Value, sampleId); // <exclude-line>
174+
}
156175
}
157176

158177
private async void WindowsUpdateHyperlinkClicked(Microsoft.UI.Xaml.Documents.Hyperlink sender, Microsoft.UI.Xaml.Documents.HyperlinkClickEventArgs args)

AIDevGallery/MainWindow.xaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148
TextChanged="SearchBox_TextChanged"
149149
UpdateTextOnSelect="False" />
150150
</TitleBar.Content>
151-
<TitleBar.Footer>
151+
<TitleBar.RightHeader>
152152
<StackPanel
153153
x:Name="DownloadProgressPanel"
154154
VerticalAlignment="Center"
@@ -196,7 +196,7 @@
196196
</Button.Flyout>
197197
</Button>
198198
</StackPanel>
199-
</TitleBar.Footer>
199+
</TitleBar.RightHeader>
200200
</TitleBar>
201201
</Grid>
202202
</winuiex:WindowEx>

AIDevGallery/Models/ModelCompatibility.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using AIDevGallery.Helpers;
55
using AIDevGallery.Samples;
66
using AIDevGallery.Utils;
7+
using Microsoft.Windows.AI;
78
using System;
89
using System.Linq;
910

@@ -33,14 +34,14 @@ public static ModelCompatibility GetModelCompatibility(ModelDetails modelDetails
3334
{
3435
var apiType = ModelTypeHelpers.ApiDefinitionDetails.FirstOrDefault(md => md.Value.Id == modelDetails.Id).Key;
3536
var availbility = WcrApiHelpers.GetApiAvailability(apiType);
36-
if (AppUtils.HasNpu() && availbility != WcrApiAvailability.NotSupported)
37+
if (availbility is AIFeatureReadyState.Ready or AIFeatureReadyState.EnsureNeeded)
3738
{
3839
compatibility = ModelCompatibilityState.Compatible;
3940
}
4041
else
4142
{
4243
compatibility = ModelCompatibilityState.NotCompatible;
43-
description = "This Windows Copilot Runtime API requires a Copilot+ PC and a Windows 11 Insider Preview Build 26120.3073 (Dev and Beta Channels).";
44+
description = $"{availbility.GetStringDescription()} This Windows Copilot Runtime API requires a Copilot+ PC and a Windows 11 Insider Preview Build 26120.3073.";
4445
}
4546
}
4647
else if (DeviceUtils.IsArm64() && modelDetails.SupportedOnQualcomm == false)

AIDevGallery/ProjectGenerator/Template/MainWindow.xaml.cs

+23-55
Original file line numberDiff line numberDiff line change
@@ -23,96 +23,64 @@ internal void ModelLoaded()
2323
ProgressRingGrid.Visibility = Visibility.Collapsed;
2424
}
2525

26-
internal async void ShowException(Exception ex, string? optionalMessage = null)
26+
internal async void ShowException(Exception? ex, string? optionalMessage = null)
2727
{
2828
var msg = optionalMessage ?? ex switch
2929
{
3030
COMException
3131
when ex.Message.Contains("the rpc server is unavailable", StringComparison.CurrentCultureIgnoreCase) =>
3232
"The WCL is in an unstable state.\nRebooting the machine will restart the WCL.",
33-
_ => $"Error:\n{ex.Message}{(optionalMessage != null ? "\n" + optionalMessage : string.Empty)}"
33+
_ => $"Error:\n{ex?.Message ?? string.Empty}{(optionalMessage != null ? "\n" + optionalMessage : string.Empty)}"
3434
};
35-
var contenText = new TextBlock
35+
36+
var errorText = new TextBlock
3637
{
3738
TextWrapping = TextWrapping.Wrap,
3839
Text = msg,
39-
HorizontalAlignment = HorizontalAlignment.Center,
40-
VerticalAlignment = VerticalAlignment.Center
40+
IsTextSelectionEnabled = true,
4141
};
4242

43-
var copyTextButton = new Button
44-
{
45-
Content = new FontIcon
46-
{
47-
FontSize = 16,
48-
Glyph = "\uF0E3"
49-
},
50-
Tag = (ex, optionalMessage),
51-
};
52-
ToolTipService.SetToolTip(copyTextButton, "Copy exception info to clipboard");
53-
copyTextButton.Click += CopyText_Click;
54-
var copyTextStack = new StackPanel
55-
{
56-
Margin = new Thickness(8),
57-
Padding = new Thickness(8),
58-
HorizontalAlignment = HorizontalAlignment.Right,
59-
VerticalAlignment = VerticalAlignment.Top,
60-
Background = (Brush)Application.Current.Resources["AcrylicBackgroundFillColorDefaultBrush"],
61-
CornerRadius = (CornerRadius)Application.Current.Resources["ControlCornerRadius"],
62-
Orientation = Orientation.Horizontal,
63-
Spacing = 8
64-
};
65-
copyTextStack.Children.Add(copyTextButton);
66-
var contentControl = new Grid
67-
{
68-
HorizontalAlignment = HorizontalAlignment.Stretch,
69-
VerticalAlignment = VerticalAlignment.Stretch,
70-
Width = 250,
71-
Height = 160
72-
};
73-
contentControl.Children.Add(contenText);
74-
contentControl.Children.Add(copyTextStack);
7543
ContentDialog exceptionDialog = new()
7644
{
77-
Title = "Error",
78-
Content = contentControl,
79-
PrimaryButtonText = "OK",
80-
SecondaryButtonText = "Reload Sample",
45+
Title = "Something went wrong",
46+
Content = errorText,
47+
PrimaryButtonText = "Copy error details",
48+
SecondaryButtonText = "Reload",
8149
XamlRoot = Content.XamlRoot,
50+
CloseButtonText = "Close",
8251
PrimaryButtonStyle = (Style)App.Current.Resources["AccentButtonStyle"],
8352
};
8453

8554
var result = await exceptionDialog.ShowAsync();
86-
if (result == ContentDialogResult.Secondary)
55+
56+
if (result == ContentDialogResult.Primary)
57+
{
58+
CopyExceptionToClipboard(ex, optionalMessage);
59+
}
60+
else if (result == ContentDialogResult.Secondary)
8761
{
8862
RootFrame.Navigate(typeof(Sample));
8963
}
9064
}
9165

92-
private static void CopyText_Click(object sender, RoutedEventArgs e)
66+
public static void CopyExceptionToClipboard(Exception? ex, string? optionalMessage)
9367
{
94-
if (sender is Button button && button.Tag is (Exception,string))
68+
string exceptionDetails = string.IsNullOrWhiteSpace(optionalMessage) ? string.Empty : optionalMessage + "\n";
69+
70+
if (ex != null)
9571
{
96-
var (ex, optionalMessage) = ((Exception, string))button.Tag;
97-
CopyExceptionToClipboard(ex, optionalMessage);
72+
exceptionDetails += GetExceptionDetails(ex);
9873
}
99-
}
100-
101-
public static void CopyExceptionToClipboard(Exception ex, string optionalMessage)
102-
{
103-
string exceptionDetails = (string.IsNullOrWhiteSpace(optionalMessage) ? string.Empty : optionalMessage + "\n") +
104-
GetExceptionDetails(ex, optionalMessage);
10574

10675
DataPackage dataPackage = new DataPackage();
10776
dataPackage.SetText(exceptionDetails);
108-
10977
Clipboard.SetContent(dataPackage);
11078
}
11179

112-
private static string GetExceptionDetails(Exception ex, string optionalMessage)
80+
private static string GetExceptionDetails(Exception ex)
11381
{
11482
var innerExceptionData = ex.InnerException == null ? "" :
115-
$"Inner Exception:\n{GetExceptionDetails(ex.InnerException, optionalMessage)}";
83+
$"Inner Exception:\n{GetExceptionDetails(ex.InnerException)}";
11684
string details = $@"Message: {ex.Message}
11785
StackTrace: {ex.StackTrace}
11886
{innerExceptionData}";

0 commit comments

Comments
 (0)