Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit 031c4d2

Browse files
authored
Update environments page UX (#2320)
* add updates to ui * fix crashes due to resource name mismatch * update feature branch to latest sdk * update InputJson to inputJson * update with latest changes * update * update to remove duplicate, resize shimmer, remove id from winget file since its not needed, and add comments * Re-add correct adaptive host file for correct theming, address some initial comments, update loading page to allow scrolling when there are tasks and actions in the action center. Fix error message spelling. * improve setup target loading page progress messaging * Fix git clone's dependsOn Id to match our new Ids for setup target flow
1 parent 1bb1d15 commit 031c4d2

File tree

52 files changed

+1528
-885
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1528
-885
lines changed

HyperVExtension/src/HyperVExtension.Common/Services/StringResource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class StringResource : IStringResource
1212

1313
public StringResource()
1414
{
15-
_resourceLoader = new ResourceLoader();
15+
_resourceLoader = new ResourceLoader("HyperVExtension/Resources");
1616
}
1717

1818
public StringResource(string name)

HyperVExtension/src/HyperVExtension/CommunicationWithGuest/ApplyConfigurationOperation.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,11 @@ private SDK.ConfigurationSetChangeData GetSdkProgressData(
190190
}
191191

192192
var wasConfigurationSuccessful = completionStatus.ResultCode == HRESULT.S_OK;
193-
if (wasConfigurationSuccessful)
193+
var isUnitResultsPresent = sdkApplyConfigurationSetResult?.UnitResults?.Count > 0;
194+
195+
// If there was no error in the completionStatus or there are unit results we'll say our operation was successful.
196+
// Even if a unit result has errors, we will display this to the user.
197+
if (wasConfigurationSuccessful || isUnitResultsPresent)
194198
{
195199
return new SDK.ApplyConfigurationResult(sdkOpenConfigurationSetResult, sdkApplyConfigurationSetResult);
196200
}

HyperVExtension/src/HyperVExtension/Constants.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,19 @@ internal sealed class Constants
77
{
88
public const string WindowsThumbnail = "ms-appx:///HyperVExtension/Assets/hyper-v-windows-default-image.jpg";
99

10-
public const string ExtensionIcon = "ms-appx:///HyperVExtension/Assets/hyper-v-provider-icon.png";
10+
// We use different icon locations for different builds. Note these are ms-resource URIs, but are used by Dev Home to load the providers icon.
11+
// from the extension package. Extensions that implement the IComputeSystemProvider interface must provide a provider icon in this format.
12+
// Dev Home will use SHLoadIndirectString (https://learn.microsoft.com/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) to load the
13+
// location of the icon from the extension package.Once it gets this location, it will load the icon from the path and display it in the UI.
14+
// Icons should be located in an extension resource.pri file which is generated at build time.
15+
// See the MakePri.exe documentation for how you can view what is in the resource.pri file, so you can find the location of your icon.
16+
// https://learn.microsoft.com/en-us/windows/uwp/app-resources/makepri-exe-command-options. (use MakePri.exe in a VS Developer Command Prompt or
17+
// Powershell window)
18+
#if CANARY_BUILD
19+
public const string ExtensionIcon = "ms-resource://Microsoft.Windows.DevHome.Canary/Files/HyperVExtension/Assets/hyper-v-provider-icon.png";
20+
#elif STABLE_BUILD
21+
public const string ExtensionIcon = "ms-resource://Microsoft.Windows.DevHome/Files/HyperVExtension/Assets/hyper-v-provider-icon.png";
22+
#else
23+
public const string ExtensionIcon = "ms-resource://Microsoft.Windows.DevHome.Dev/Files/HyperVExtension/Assets/hyper-v-provider-icon.png";
24+
#endif
1125
}

HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ namespace HyperVExtension.Models;
3030
/// <summary> Class that represents a Hyper-V virtual machine object. </summary>
3131
public class HyperVVirtualMachine : IComputeSystem
3232
{
33-
private readonly string errorResourceKey = "ErrorPerformingOperation";
33+
private readonly string _errorResourceKey = "ErrorPerformingOperation";
3434

35-
private readonly string currentCheckpointKey = "CurrentCheckpoint";
36-
37-
private readonly string operationErrorString;
35+
private readonly string _currentCheckpointKey = "CurrentCheckpoint";
3836

3937
private readonly IStringResource _stringResource;
4038

@@ -88,6 +86,9 @@ public class HyperVVirtualMachine : IComputeSystem
8886

8987
public bool IsDeleted => _psObjectHelper.MemberNameToValue<bool>(HyperVStrings.IsDeleted);
9088

89+
// Temporary will need to add more error strings for different operations.
90+
public string OperationErrorUnknownString => _stringResource.GetLocalized(_errorResourceKey);
91+
9192
// TODO: make getting this list dynamic so we can remove operations based on OS version.
9293
public ComputeSystemOperations SupportedOperations => ComputeSystemOperations.Start |
9394
ComputeSystemOperations.ShutDown |
@@ -113,7 +114,6 @@ public HyperVVirtualMachine(IHost host, IHyperVManager hyperVManager, IStringRes
113114
_hyperVManager = hyperVManager;
114115
_psObjectHelper = new(psObject);
115116
_stringResource = stringResource;
116-
operationErrorString = _stringResource.GetLocalized(errorResourceKey);
117117
}
118118

119119
public IEnumerable<HyperVVirtualMachineHardDisk> GetHardDrives()
@@ -193,7 +193,7 @@ private ComputeSystemOperationResult Start(string options)
193193
{
194194
StateChanged(this, ComputeSystemState.Unknown);
195195
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.Start), ex);
196-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
196+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
197197
}
198198
}
199199

@@ -223,7 +223,7 @@ public IAsyncOperation<ComputeSystemOperationResult> ShutDownAsync(string option
223223
{
224224
StateChanged(this, ComputeSystemState.Unknown);
225225
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.ShutDown));
226-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
226+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
227227
}
228228
}).AsAsyncOperation();
229229
}
@@ -254,7 +254,7 @@ public IAsyncOperation<ComputeSystemOperationResult> TerminateAsync(string optio
254254
{
255255
StateChanged(this, ComputeSystemState.Unknown);
256256
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.Terminate), ex);
257-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
257+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
258258
}
259259
}).AsAsyncOperation();
260260
}
@@ -279,7 +279,7 @@ public IAsyncOperation<ComputeSystemOperationResult> DeleteAsync(string options)
279279
{
280280
StateChanged(this, ComputeSystemState.Unknown);
281281
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.Delete), ex);
282-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
282+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
283283
}
284284
}).AsAsyncOperation();
285285
}
@@ -310,7 +310,7 @@ public IAsyncOperation<ComputeSystemOperationResult> SaveAsync(string options)
310310
{
311311
StateChanged(this, ComputeSystemState.Unknown);
312312
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.Save), ex);
313-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
313+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
314314
}
315315
}).AsAsyncOperation();
316316
}
@@ -341,7 +341,7 @@ public IAsyncOperation<ComputeSystemOperationResult> PauseAsync(string options)
341341
{
342342
StateChanged(this, ComputeSystemState.Unknown);
343343
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.Pause), ex);
344-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
344+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
345345
}
346346
}).AsAsyncOperation();
347347
}
@@ -372,7 +372,7 @@ public IAsyncOperation<ComputeSystemOperationResult> ResumeAsync(string options)
372372
{
373373
StateChanged(this, ComputeSystemState.Unknown);
374374
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.Resume), ex);
375-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
375+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
376376
}
377377
}).AsAsyncOperation();
378378
}
@@ -394,7 +394,7 @@ public IAsyncOperation<ComputeSystemOperationResult> CreateSnapshotAsync(string
394394
catch (Exception ex)
395395
{
396396
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.CreateSnapshot), ex);
397-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
397+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
398398
}
399399
}).AsAsyncOperation();
400400
}
@@ -417,7 +417,7 @@ public IAsyncOperation<ComputeSystemOperationResult> RevertSnapshotAsync(string
417417
catch (Exception ex)
418418
{
419419
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.RevertSnapshot), ex);
420-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
420+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
421421
}
422422
}).AsAsyncOperation();
423423
}
@@ -440,7 +440,7 @@ public IAsyncOperation<ComputeSystemOperationResult> DeleteSnapshotAsync(string
440440
catch (Exception ex)
441441
{
442442
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.DeleteSnapshot), ex);
443-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
443+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
444444
}
445445
}).AsAsyncOperation();
446446
}
@@ -458,7 +458,7 @@ public IAsyncOperation<ComputeSystemOperationResult> ConnectAsync(string options
458458
catch (Exception ex)
459459
{
460460
Logging.Logger()?.ReportError($"Failed to launch vmconnect on {DateTime.Now}: VM details: {this}", ex);
461-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
461+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
462462
}
463463
}).AsAsyncOperation();
464464
}
@@ -488,7 +488,7 @@ public IAsyncOperation<ComputeSystemOperationResult> RestartAsync(string options
488488
{
489489
StateChanged(this, ComputeSystemState.Unknown);
490490
Logging.Logger()?.ReportError(OperationErrorString(ComputeSystemOperations.Restart), ex);
491-
return new ComputeSystemOperationResult(ex, operationErrorString, ex.Message);
491+
return new ComputeSystemOperationResult(ex, OperationErrorUnknownString, ex.Message);
492492
}
493493
}).AsAsyncOperation();
494494
}
@@ -529,7 +529,7 @@ public IAsyncOperation<IEnumerable<ComputeSystemProperty>> GetComputeSystemPrope
529529
ComputeSystemProperty.Create(ComputeSystemPropertyKind.AssignedMemorySizeInBytes, MemoryAssigned),
530530
ComputeSystemProperty.Create(ComputeSystemPropertyKind.AssignedMemorySizeInBytes, totalDiskSize),
531531
ComputeSystemProperty.Create(ComputeSystemPropertyKind.UptimeIn100ns, Uptime),
532-
ComputeSystemProperty.CreateCustom(ParentCheckpointName, _stringResource.GetLocalized(currentCheckpointKey), null),
532+
ComputeSystemProperty.CreateCustom(ParentCheckpointName, _stringResource.GetLocalized(_currentCheckpointKey), null),
533533
};
534534

535535
return properties.AsEnumerable();
@@ -546,7 +546,7 @@ public IAsyncOperation<ComputeSystemOperationResult> ModifyPropertiesAsync(strin
546546
{
547547
// This is temporary until we have a proper implementation for this.
548548
var notImplementedException = new NotImplementedException($"Method not implemented by Hyper-V Compute Systems: VM details: {this}");
549-
return Task.FromResult(new ComputeSystemOperationResult(notImplementedException, operationErrorString, notImplementedException.Message)).AsAsyncOperation();
549+
return Task.FromResult(new ComputeSystemOperationResult(notImplementedException, OperationErrorUnknownString, notImplementedException.Message)).AsAsyncOperation();
550550
}
551551

552552
public SDK.ApplyConfigurationResult ApplyConfiguration(ApplyConfigurationOperation operation)

HyperVExtension/src/HyperVExtension/Providers/HyperVProvider.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ public class HyperVProvider : IComputeSystemProvider
1515
{
1616
private readonly string errorResourceKey = "ErrorPerformingOperation";
1717

18-
private readonly string operationErrorString;
19-
2018
private readonly IStringResource _stringResource;
2119

2220
private readonly IHyperVManager _hyperVManager;
2321

22+
// Temporary will need to add more error strings for different operations.
23+
public string OperationErrorString => _stringResource.GetLocalized(errorResourceKey);
24+
2425
public HyperVProvider(IHyperVManager hyperVManager, IStringResource stringResource)
2526
{
2627
_hyperVManager = hyperVManager;
2728
_stringResource = stringResource;
28-
operationErrorString = _stringResource.GetLocalized(errorResourceKey);
2929
}
3030

3131
/// <summary> Gets or sets the default compute system properties. </summary>
@@ -74,7 +74,7 @@ public IAsyncOperation<ComputeSystemsResult> GetComputeSystemsAsync(IDeveloperId
7474
catch (Exception ex)
7575
{
7676
Logging.Logger()?.ReportError($"Failed to retrieved all virtual machines on: {DateTime.Now}", ex);
77-
return new ComputeSystemsResult(ex, operationErrorString, ex.Message);
77+
return new ComputeSystemsResult(ex, OperationErrorString, ex.Message);
7878
}
7979
}).AsAsyncOperation();
8080
}
@@ -83,14 +83,14 @@ public ComputeSystemAdaptiveCardResult CreateAdaptiveCardSessionForDeveloperId(I
8383
{
8484
// This won't be supported until creation is supported.
8585
var notImplementedException = new NotImplementedException($"Method not implemented by Hyper-V Compute System Provider");
86-
return new ComputeSystemAdaptiveCardResult(notImplementedException, operationErrorString, notImplementedException.Message);
86+
return new ComputeSystemAdaptiveCardResult(notImplementedException, OperationErrorString, notImplementedException.Message);
8787
}
8888

8989
public ComputeSystemAdaptiveCardResult CreateAdaptiveCardSessionForComputeSystem(IComputeSystem computeSystem, ComputeSystemAdaptiveCardKind sessionKind)
9090
{
9191
// This won't be supported until property modification is supported.
9292
var notImplementedException = new NotImplementedException($"Method not implemented by Hyper-V Compute System Provider");
93-
return new ComputeSystemAdaptiveCardResult(notImplementedException, operationErrorString, notImplementedException.Message);
93+
return new ComputeSystemAdaptiveCardResult(notImplementedException, OperationErrorString, notImplementedException.Message);
9494
}
9595

9696
// This will be implemented in a future release, but will be available for Dev Environments 1.0.

common/Contracts/IComputeSystemService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
using System.Threading.Tasks;
77
using DevHome.Common.Environments.Models;
88
using DevHome.Common.Models;
9+
using DevHome.Common.Services;
910
using Microsoft.Windows.DevHome.SDK;
1011

1112
namespace DevHome.Common.Contracts.Services;
1213

1314
public interface IComputeSystemService
1415
{
15-
public Task<Dictionary<IComputeSystemProvider, List<IDeveloperId>>> GetComputeSystemProvidersAsync();
16+
public Task<List<ComputeSystemProviderDetails>> GetComputeSystemProvidersAsync();
1617
}

common/Environments/CustomControls/CardBody.xaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,23 @@
4141
-->
4242
<StackPanel
4343
Grid.Column="1"
44+
Grid.ColumnSpan="2"
4445
Style="{StaticResource CardBodyStackPanelStyle}">
4546
<StackPanel Orientation="Horizontal">
4647
<TextBlock
4748
Style="{StaticResource CardBodyStackPanelTextBlockStyle}"
48-
Text="{x:Bind ComputeSystemTitle, Mode=OneWay}"/>
49+
Text="{x:Bind ComputeSystemTitle, Mode=OneWay}"
50+
IsTextSelectionEnabled="True"/>
4951
<TextBlock
5052
Style="{StaticResource CardBodyStackPanelAltTextBlockStyle}"
51-
Text="{x:Bind ComputeSystemAlternativeTitle, Mode=OneWay}"/>
53+
Text="{x:Bind ComputeSystemAlternativeTitle, Mode=OneWay}"
54+
IsTextSelectionEnabled="True"/>
5255
</StackPanel>
5356
<Grid
5457
ColumnSpacing="{StaticResource ContainerElementSpacing}">
5558
<Grid.ColumnDefinitions>
5659
<ColumnDefinition Width="Auto" />
57-
<ColumnDefinition Width="*" />
60+
<ColumnDefinition Width="Auto" />
5861
</Grid.ColumnDefinitions>
5962
<!-- Colored dot that indicates the visual state of the compute system. -->
6063
<Ellipse
@@ -65,7 +68,8 @@
6568
<TextBlock
6669
Grid.Column="1"
6770
Text="{x:Bind CardState, Converter={StaticResource CardStateToLocalizedTextConverter}, Mode=OneWay}"
68-
Style="{StaticResource CardBodyStateTextBlockStyle}"/>
71+
Style="{StaticResource CardBodyStateTextBlockStyle}"
72+
IsTextSelectionEnabled="True"/>
6973
</Grid>
7074
<!-- Wrap panel from community toolkit that will display properties of variable length. -->
7175
<ItemsRepeater

0 commit comments

Comments
 (0)