From 60ed7f9dc71b5a01d0ae39ecfed46dbc4bf1ff12 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Fri, 23 Feb 2024 11:27:17 -0800 Subject: [PATCH 01/17] WIP --- .../SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs | 2 ++ .../DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs index 23416750f..5ae604776 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs @@ -129,6 +129,7 @@ private static IServiceCollection AddLoading(this IServiceCollection services) { // View models services.AddTransient(); + services.AddTransient(); return services; } @@ -150,6 +151,7 @@ private static IServiceCollection AddRepoConfig(this IServiceCollection services // Services services.AddTransient(); + services.AddTransient(); return services; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs index 883598d65..35337eed7 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs @@ -88,7 +88,7 @@ public bool ShouldAutoCheckDevDriveCheckbox /// All repositories the user wants to clone. /// [ObservableProperty] - private ObservableCollection _repoReviewItems = new(); + private ObservableCollection _repoReviewItems = new(); public IDevDriveManager DevDriveManager => _devDriveManager; From 4f0f3d85bd7fdbaa022cf6be57ad506ed3498b80 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Wed, 28 Feb 2024 10:21:37 -0800 Subject: [PATCH 02/17] Builds and runs. no special UI though. :( --- .../DevHome.SetupFlow.csproj | 20 ++++++++ .../Extensions/ServiceExtensions.cs | 13 ++++- .../DevHome.SetupFlow/Models/CloneRepoTask.cs | 36 +++++++++++++- .../DevHome.SetupFlow/Models/ConfigureTask.cs | 8 +++- .../Models/CreateDevDriveTask.cs | 3 ++ .../DevHome.SetupFlow/Models/ISetupTask.cs | 3 ++ .../Models/InstallPackageTask.cs | 3 ++ .../TaskGroups/RepoConfigTaskGroup.cs | 4 +- .../CloneRepoSummaryInformation.xaml | 14 ++++++ .../CloneRepoSummaryInformation.xaml.cs | 30 ++++++++++++ .../ConfigurationSummaryInformation.xaml | 15 ++++++ .../ConfigurationSummaryInformation.xaml.cs | 27 +++++++++++ .../CreateDevDriveSummaryInformation.xaml | 15 ++++++ .../CreateDevDriveSummaryInformation.xaml.cs | 27 +++++++++++ .../Templates/EmptySummaryInformation.xaml | 15 ++++++ .../Templates/EmptySummaryInformation.xaml.cs | 27 +++++++++++ .../InstallPackageSummaryInformation.xaml | 15 ++++++ .../InstallPackageSummaryInformation.xaml.cs | 27 +++++++++++ .../SummaryInformationTemplateSelector.cs | 48 +++++++++++++++++++ ...loneRepoSummaryInformationFileViewModel.cs | 15 ++++++ .../ViewModels/ConfigurationFileViewModel.cs | 9 +++- ...onfigurationSummaryInformationViewModel.cs | 10 ++++ ...eateDevDriveSummaryInformationViewModel.cs | 15 ++++++ .../EmptySummaryInformationViewModel.cs | 10 ++++ .../ISummaryInformationViewModel.cs | 8 ++++ ...stallPackageSummaryInformationViewModel.cs | 10 ++++ .../ViewModels/LoadingMessageViewModel.cs | 8 +--- .../ViewModels/LoadingViewModel.cs | 31 ++++++------ .../ViewModels/RepoConfigViewModel.cs | 2 +- .../ViewModels/SummaryViewModel.cs | 4 ++ .../DevHome.SetupFlow/Views/SummaryView.xaml | 22 +++++++++ 31 files changed, 465 insertions(+), 29 deletions(-) create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs diff --git a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj index bdc73d242..7346c9d80 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj +++ b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj @@ -39,6 +39,21 @@ Always + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + $(DefaultXamlRuntime) Designer @@ -74,6 +89,11 @@ + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs index 5ae604776..6a534625d 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs @@ -31,6 +31,7 @@ public static IServiceCollection AddSetupFlow(this IServiceCollection services, services.AddRepoConfig(); services.AddReview(); services.AddSummary(); + services.AddSummaryInformation(); // View-models services.AddSingleton(); @@ -110,6 +111,17 @@ private static IServiceCollection AddConfigurationFile(this IServiceCollection s return services; } + private static IServiceCollection AddSummaryInformation(this IServiceCollection services) + { + // View models + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + return services; + } + private static IServiceCollection AddDevDrive(this IServiceCollection services) { // View models @@ -151,7 +163,6 @@ private static IServiceCollection AddRepoConfig(this IServiceCollection services // Services services.AddTransient(); - services.AddTransient(); return services; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index 098024691..7297da8ec 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -4,17 +4,22 @@ extern alias Projection; using System; +using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using DevHome.Common.Extensions; using DevHome.Common.Services; using DevHome.Common.TelemetryEvents; using DevHome.Common.TelemetryEvents.SetupFlow; using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Services; +using DevHome.SetupFlow.ViewModels; using DevHome.Telemetry; +using Microsoft.Extensions.Hosting; using Microsoft.Windows.DevHome.SDK; using Projection::DevHome.SetupFlow.ElevatedComponent; using Windows.Foundation; @@ -27,6 +32,8 @@ namespace DevHome.SetupFlow.Models; /// public partial class CloneRepoTask : ObservableObject, ISetupTask { + private readonly IHost _host; + private readonly Guid _activityId; /// @@ -127,13 +134,15 @@ public bool DependsOnDevDriveToBeInstalled get; set; } + public ISummaryInformationViewModel SummaryScreenInformation { get; private set; } + /// /// Initializes a new instance of the class. /// /// Repository will be placed here. at _cloneLocation.FullName /// The repository to clone /// Credentials needed to clone a private repo - public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, IDeveloperId developerId, IStringResource stringResource, string providerName, Guid activityId) + public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, IDeveloperId developerId, IStringResource stringResource, string providerName, Guid activityId, IHost host) { _cloneLocation = cloneLocation; this.RepositoryToClone = repositoryToClone; @@ -143,6 +152,7 @@ public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo clone _stringResource = stringResource; _repositoryProvider = repositoryProvider; _activityId = activityId; + _host = host; } /// @@ -151,7 +161,7 @@ public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo clone /// /// Repository will be placed here, at _cloneLocation.FullName /// The repository to clone - public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, IStringResource stringResource, string providerName, Guid activityId) + public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, IStringResource stringResource, string providerName, Guid activityId, IHost host) { _cloneLocation = cloneLocation; this.RepositoryToClone = repositoryToClone; @@ -161,6 +171,7 @@ public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo clone _stringResource = stringResource; _repositoryProvider = repositoryProvider; _activityId = activityId; + _host = host; } private void SetMessages(IStringResource stringResource) @@ -227,7 +238,28 @@ IAsyncOperation ISetupTask.Execute() return TaskFinishedState.Failure; } + var configurationFileLocations = new List(); + + var configurationDirectory = Path.Join(_cloneLocation.FullName, ".configurations"); + if (Directory.Exists(configurationDirectory)) + { + foreach (var configurationFile in Directory.EnumerateFiles(configurationDirectory)) + { + if (configurationFile.EndsWith(".dsc.yaml", StringComparison.OrdinalIgnoreCase) || + configurationFile.EndsWith(".winget", StringComparison.OrdinalIgnoreCase)) + { + configurationFileLocations.Add(configurationFile); + } + } + + SummaryScreenInformation = _host.GetService(); + var fileToUse = configurationFileLocations.OrderBy(x => File.GetLastWriteTime(x)).FirstOrDefault(); + (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).FileName = fileToUse; + (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).RepoName = RepositoryName; + } + WasCloningSuccessful = true; + return TaskFinishedState.Success; }).AsAsyncOperation(); } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs index 316c9af07..4efb339d0 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs @@ -8,9 +8,12 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using DevHome.Common.Extensions; using DevHome.SetupFlow.Common.Contracts; using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Services; +using DevHome.SetupFlow.ViewModels; +using Microsoft.Extensions.Hosting; using Projection::DevHome.SetupFlow.ElevatedComponent; using Windows.Foundation; using Windows.Storage; @@ -39,11 +42,14 @@ public IList UnitResults get; private set; } + public ISummaryInformationViewModel SummaryScreenInformation { get; } + public ConfigureTask( ISetupFlowStringResource stringResource, IDesiredStateConfiguration dsc, StorageFile file, - Guid activityId) + Guid activityId, + IHost host) { _stringResource = stringResource; _dsc = dsc; diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs index f16ff2b1f..713545757 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs @@ -16,6 +16,7 @@ using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Common.TelemetryEvents; using DevHome.SetupFlow.Services; +using DevHome.SetupFlow.ViewModels; using DevHome.Telemetry; using Microsoft.Extensions.Hosting; using Projection::DevHome.SetupFlow.ElevatedComponent; @@ -44,6 +45,8 @@ public IDevDrive DevDrive get; set; } + public ISummaryInformationViewModel SummaryScreenInformation { get; } + public CreateDevDriveTask(IDevDrive devDrive, IHost host, Guid activityId, ISetupFlowStringResource stringResource) { DevDrive = devDrive; diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs index 8304c9c96..67ae12291 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs @@ -3,6 +3,7 @@ extern alias Projection; +using DevHome.SetupFlow.ViewModels; using Projection::DevHome.SetupFlow.ElevatedComponent; using Windows.Foundation; @@ -98,4 +99,6 @@ public abstract bool DependsOnDevDriveToBeInstalled /// Use this event to insert a message into the loading screen. /// public event ChangeMessageHandler AddMessage; + + public ISummaryInformationViewModel SummaryScreenInformation { get; } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs index beb29f68f..bca69afed 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs @@ -10,6 +10,7 @@ using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Exceptions; using DevHome.SetupFlow.Services; +using DevHome.SetupFlow.ViewModels; using DevHome.Telemetry; using Microsoft.Management.Deployment; using Projection::DevHome.SetupFlow.ElevatedComponent; @@ -53,6 +54,8 @@ public bool DependsOnDevDriveToBeInstalled get; } + public ISummaryInformationViewModel SummaryScreenInformation { get; } + public InstallPackageTask( IWindowsPackageManager wpm, ISetupFlowStringResource stringResource, diff --git a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs index 5b529fe75..18febb6b3 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs @@ -69,11 +69,11 @@ public void SaveSetupTaskInformation(List cloningInformation CloneRepoTask task; if (cloningInformation.OwningAccount == null) { - task = new CloneRepoTask(cloningInformation.RepositoryProvider, new DirectoryInfo(cloningInformation.ClonePath), cloningInformation.RepositoryToClone, _stringResource, cloningInformation.RepositoryProviderDisplayName, _activityId); + task = new CloneRepoTask(cloningInformation.RepositoryProvider, new DirectoryInfo(cloningInformation.ClonePath), cloningInformation.RepositoryToClone, _stringResource, cloningInformation.RepositoryProviderDisplayName, _activityId, _host); } else { - task = new CloneRepoTask(cloningInformation.RepositoryProvider, new DirectoryInfo(cloningInformation.ClonePath), cloningInformation.RepositoryToClone, cloningInformation.OwningAccount, _stringResource, cloningInformation.RepositoryProviderDisplayName, _activityId); + task = new CloneRepoTask(cloningInformation.RepositoryProvider, new DirectoryInfo(cloningInformation.ClonePath), cloningInformation.RepositoryToClone, cloningInformation.OwningAccount, _stringResource, cloningInformation.RepositoryProviderDisplayName, _activityId, _host); } if (cloningInformation.CloneToDevDrive) diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml new file mode 100644 index 000000000..9a0964e94 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs new file mode 100644 index 000000000..641d1371a --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using Windows.Foundation; +using Windows.Foundation.Collections; + +namespace DevHome.SetupFlow.Templates; + +/// +/// An empty page that can be used on its own or navigated to within a Frame. +/// +public sealed partial class CloneRepoSummaryInformation : ResourceDictionary +{ + public CloneRepoSummaryInformation() + { + this.InitializeComponent(); + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml new file mode 100644 index 000000000..383e43cf9 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs new file mode 100644 index 000000000..167d4c77a --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using Windows.Foundation; +using Windows.Foundation.Collections; + +namespace DevHome.SetupFlow.Templates; + +public sealed partial class ConfigurationSummaryInformation : ResourceDictionary +{ + public ConfigurationSummaryInformation() + { + this.InitializeComponent(); + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml new file mode 100644 index 000000000..255738a25 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml.cs new file mode 100644 index 000000000..9dbaf1de9 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using Windows.Foundation; +using Windows.Foundation.Collections; + +namespace DevHome.SetupFlow.Templates; + +public sealed partial class CreateDevDriveSummaryInformation : ResourceDictionary +{ + public CreateDevDriveSummaryInformation() + { + this.InitializeComponent(); + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml new file mode 100644 index 000000000..a05cba9e5 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs new file mode 100644 index 000000000..6870989f1 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using Windows.Foundation; +using Windows.Foundation.Collections; + +namespace DevHome.SetupFlow.Templates; + +public sealed partial class EmptySummaryInformation : ResourceDictionary +{ + public EmptySummaryInformation() + { + this.InitializeComponent(); + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml new file mode 100644 index 000000000..8f8c24b09 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs new file mode 100644 index 000000000..ae71a2690 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using Windows.Foundation; +using Windows.Foundation.Collections; + +namespace DevHome.SetupFlow.Templates; + +public sealed partial class InstallPackageSummaryInformation : ResourceDictionary +{ + public InstallPackageSummaryInformation() + { + this.InitializeComponent(); + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs new file mode 100644 index 000000000..e860abcf5 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using DevHome.SetupFlow.ViewModels; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace DevHome.SetupFlow.Templates; + +public class SummaryInformationTemplateSelector : DataTemplateSelector +{ + public DataTemplate CloneRepoDataTemplate + { + get; set; + } + + public DataTemplate ConfigurationDataTemplate + { + get; set; + } + + public DataTemplate CreateDevDriveDataTemplate + { + get; set; + } + + public DataTemplate InstallPackageDataTemplate + { + get; set; + } + + public DataTemplate EmptyDataTemplate + { + get; set; + } + + protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) + { + return item switch + { + CloneRepoSummaryInformationViewModel => CloneRepoDataTemplate, + ConfigurationSummaryInformationViewModel => ConfigurationDataTemplate, + CreateDevDriveSummaryInformationViewModel => CreateDevDriveDataTemplate, + InstallPackageSummaryInformationViewModel => InstallPackageDataTemplate, + _ => EmptyDataTemplate, + }; + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs new file mode 100644 index 000000000..e70d54336 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using CommunityToolkit.Mvvm.ComponentModel; + +namespace DevHome.SetupFlow.ViewModels; + +public partial class CloneRepoSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel +{ + [ObservableProperty] + private string _fileName; + + [ObservableProperty] + private string _repoName; +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationFileViewModel.cs index a5a03c02b..31a329da6 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationFileViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationFileViewModel.cs @@ -13,6 +13,7 @@ using DevHome.SetupFlow.Models; using DevHome.SetupFlow.Services; using DevHome.Telemetry; +using Microsoft.Extensions.Hosting; using Microsoft.UI.Xaml; using WinUIEx; @@ -20,6 +21,8 @@ namespace DevHome.SetupFlow.ViewModels; public partial class ConfigurationFileViewModel : SetupPageViewModelBase { + private readonly IHost _host; + private readonly IDesiredStateConfiguration _dsc; public List TaskList { get; } = new List(); @@ -42,7 +45,8 @@ public partial class ConfigurationFileViewModel : SetupPageViewModelBase public ConfigurationFileViewModel( ISetupFlowStringResource stringResource, IDesiredStateConfiguration dsc, - SetupFlowOrchestrator orchestrator) + SetupFlowOrchestrator orchestrator, + IHost host) : base(stringResource, orchestrator) { _dsc = dsc; @@ -50,6 +54,7 @@ public ConfigurationFileViewModel( // Configure navigation bar NextPageButtonText = StringResource.GetLocalized(StringResourceKey.SetUpButton); IsStepPage = false; + _host = host; } partial void OnReadAndAgreeChanged(bool value) @@ -117,7 +122,7 @@ public async Task PickConfigurationFileAsync() Configuration = new(file.Path); Orchestrator.FlowTitle = StringResource.GetLocalized(StringResourceKey.ConfigurationViewTitle, Configuration.Name); await _dsc.ValidateConfigurationAsync(file.Path, Orchestrator.ActivityId); - TaskList.Add(new(StringResource, _dsc, file, Orchestrator.ActivityId)); + TaskList.Add(new(StringResource, _dsc, file, Orchestrator.ActivityId, _host)); return true; } catch (OpenConfigurationSetException e) diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs new file mode 100644 index 000000000..d9753e167 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using CommunityToolkit.Mvvm.ComponentModel; + +namespace DevHome.SetupFlow.ViewModels; + +public partial class ConfigurationSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel +{ +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs new file mode 100644 index 000000000..50fac1ad7 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace DevHome.SetupFlow.ViewModels; + +public partial class CreateDevDriveSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel +{ +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs new file mode 100644 index 000000000..dde1eaa52 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using CommunityToolkit.Mvvm.ComponentModel; + +namespace DevHome.SetupFlow.ViewModels; + +public partial class EmptySummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel +{ +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs new file mode 100644 index 000000000..7cf73b42c --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace DevHome.SetupFlow.ViewModels; + +public interface ISummaryInformationViewModel +{ +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs new file mode 100644 index 000000000..4602c9570 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using CommunityToolkit.Mvvm.ComponentModel; + +namespace DevHome.SetupFlow.ViewModels; + +public partial class InstallPackageSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel +{ +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs index 1bfff0da8..d077d506c 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs @@ -16,7 +16,8 @@ public partial class LoadingMessageViewModel : ObservableObject /// /// Gets the message to display in the loading screen. /// - public string MessageToShow { get; } + [ObservableProperty] + private string _messageToShow; /// /// If the progress ring should be shown. Only show a progress ring when the task is running. @@ -45,9 +46,4 @@ public void TextTrimmed() { IsRepoNameTrimmed = true; } - - public LoadingMessageViewModel(string messageToShow) - { - MessageToShow = messageToShow; - } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs index 582a1615e..c411f8a26 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs @@ -40,10 +40,6 @@ public partial class LoadingViewModel : SetupPageViewModelBase private static readonly BitmapImage LightError = new(new Uri("ms-appx:///DevHome.SetupFlow/Assets/LightError.png")); private static readonly BitmapImage LightSuccess = new(new Uri("ms-appx:///DevHome.SetupFlow/Assets/LightSuccess.png")); -#pragma warning disable SA1310 // Field names should not contain underscore - private const int NUMBER_OF_PARALLEL_RUNNING_TASKS = 5; -#pragma warning restore SA1310 // Field names should not contain underscore - #pragma warning disable SA1310 // Field names should not contain underscore private const int MAX_RETRIES = 1; #pragma warning restore SA1310 // Field names should not contain underscore @@ -79,6 +75,9 @@ public partial class LoadingViewModel : SetupPageViewModelBase [ObservableProperty] private ObservableCollection _messages; + [ObservableProperty] + private ObservableCollection _summaryInformation; + /// /// List of all messages that shows up in the "action center" of the loading screen. /// @@ -180,7 +179,8 @@ public void AddMessage(string message) { Application.Current.GetService().DispatcherQueue.TryEnqueue(() => { - var messageToDisplay = new LoadingMessageViewModel(message); + var messageToDisplay = _host.GetService(); + messageToDisplay.MessageToShow = message; messageToDisplay.ShouldShowStatusSymbolIcon = false; messageToDisplay.ShouldShowProgressRing = false; Messages.Insert(Messages.Count - _numberOfExecutingTasks, messageToDisplay); @@ -207,6 +207,7 @@ public LoadingViewModel( ActionCenterItems = new(); Messages = new(); _activityId = orchestrator.ActivityId; + _summaryInformation = new ObservableCollection(); } /// @@ -328,7 +329,8 @@ private void ChangeMessage(TaskInformation information, LoadingMessageViewModel Messages.Insert(Messages.Count - _numberOfExecutingTasks, loadingMessage); // Add the "Execution finished" message - var newLoadingScreenMessage = new LoadingMessageViewModel(stringToReplace); + var newLoadingScreenMessage = _host.GetService(); + newLoadingScreenMessage.MessageToShow = stringToReplace; newLoadingScreenMessage.StatusSymbolIcon = statusSymbolIcon; newLoadingScreenMessage.ShouldShowProgressRing = false; newLoadingScreenMessage.ShouldShowStatusSymbolIcon = true; @@ -375,19 +377,14 @@ await Task.Run(async () => } } - var options = new ParallelOptions() - { - MaxDegreeOfParallelism = NUMBER_OF_PARALLEL_RUNNING_TASKS, - }; - // Run all tasks that don't need dev drive installed. - await Parallel.ForEachAsync(tasksToRunFirst, options, async (taskInformation, token) => + await Parallel.ForEachAsync(tasksToRunFirst, async (taskInformation, token) => { await StartTaskAndReportResult(window, taskInformation); }); // Run all the tasks that need dev drive installed. - await Parallel.ForEachAsync(tasksToRunSecond, options, async (taskInformation, token) => + await Parallel.ForEachAsync(tasksToRunSecond, async (taskInformation, token) => { await StartTaskAndReportResult(window, taskInformation); }); @@ -432,7 +429,8 @@ private async Task StartTaskAndReportResult(WinUIEx.WindowEx window, TaskInforma // Start the task and wait for it to complete. try { - var loadingMessage = new LoadingMessageViewModel(taskInformation.MessageToShow); + var loadingMessage = _host.GetService(); + loadingMessage.MessageToShow = taskInformation.MessageToShow; window.DispatcherQueue.TryEnqueue(() => { TasksStarted++; @@ -458,6 +456,11 @@ private async Task StartTaskAndReportResult(WinUIEx.WindowEx window, TaskInforma window.DispatcherQueue.TryEnqueue(() => { + if (taskInformation.TaskToExecute.SummaryScreenInformation != null) + { + SummaryInformation.Add(taskInformation.TaskToExecute.SummaryScreenInformation); + } + // Keep decrement inside TryEnqueue to encorce "locking" _numberOfExecutingTasks--; ChangeMessage(taskInformation, loadingMessage, taskFinishedState); diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs index 35337eed7..883598d65 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs @@ -88,7 +88,7 @@ public bool ShouldAutoCheckDevDriveCheckbox /// All repositories the user wants to clone. /// [ObservableProperty] - private ObservableCollection _repoReviewItems = new(); + private ObservableCollection _repoReviewItems = new(); public IDevDriveManager DevDriveManager => _devDriveManager; diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs index 13a9faa32..ebb309ce7 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs @@ -40,6 +40,9 @@ public partial class SummaryViewModel : SetupPageViewModelBase private readonly PackageProvider _packageProvider; private readonly IAppManagementInitializer _appManagementInitializer; + [ObservableProperty] + private ObservableCollection _summaryInformation; + [ObservableProperty] private List _failedTasks = new(); @@ -203,6 +206,7 @@ protected async override Task OnFirstNavigateToAsync() if (flowPage is LoadingViewModel loadingViewModel) { failedTasks = loadingViewModel.FailedTasks; + SummaryInformation = loadingViewModel.SummaryInformation; } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml index cbd8a7598..8c86b5001 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml @@ -6,6 +6,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:converters="using:CommunityToolkit.WinUI.Converters" xmlns:viewModels="using:DevHome.SetupFlow.ViewModels" + xmlns:templates="using:DevHome.SetupFlow.Templates" xmlns:i="using:Microsoft.Xaml.Interactivity" xmlns:ic="using:Microsoft.Xaml.Interactions.Core" xmlns:models="using:DevHome.SetupFlow.Models" @@ -48,6 +49,11 @@ + + + + + @@ -176,6 +182,22 @@ + + + + + + + + + + From 19c1ffdf4adffcca8698554d1b41b03f9e4c4c48 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Tue, 12 Mar 2024 16:02:39 -0700 Subject: [PATCH 03/17] Works. Looks good. View File works. --- .../DevHome.SetupFlow.csproj | 20 +------- .../Extensions/ServiceExtensions.cs | 3 -- .../DevHome.SetupFlow/Models/CloneRepoTask.cs | 2 +- .../CloneRepoSummaryInformation.xaml | 14 ------ .../CloneRepoSummaryInformation.xaml.cs | 30 ------------ .../ConfigurationSummaryInformation.xaml | 15 ------ .../ConfigurationSummaryInformation.xaml.cs | 27 ----------- .../CreateDevDriveSummaryInformation.xaml | 15 ------ .../Templates/EmptySummaryInformation.xaml | 15 ------ .../Templates/EmptySummaryInformation.xaml.cs | 27 ----------- .../InstallPackageSummaryInformation.xaml | 15 ------ .../InstallPackageSummaryInformation.xaml.cs | 27 ----------- .../SummaryInformationTemplateSelector.cs | 48 ------------------- ...loneRepoSummaryInformationFileViewModel.cs | 22 ++++++++- ...onfigurationSummaryInformationViewModel.cs | 1 + ...eateDevDriveSummaryInformationViewModel.cs | 1 + .../EmptySummaryInformationViewModel.cs | 1 + .../ISummaryInformationViewModel.cs | 1 + ...stallPackageSummaryInformationViewModel.cs | 1 + .../ViewModels/LoadingViewModel.cs | 5 -- .../ViewModels/SummaryViewModel.cs | 27 ++++++++++- .../CloneRepoSummaryInformationView.xaml | 43 +++++++++++++++++ .../CloneRepoSummaryInformationView.xaml.cs} | 9 ++-- .../DevHome.SetupFlow/Views/SummaryView.xaml | 41 +++++++--------- .../Views/SummaryView.xaml.cs | 6 ++- 25 files changed, 125 insertions(+), 291 deletions(-) delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml rename tools/SetupFlow/DevHome.SetupFlow/{Templates/CreateDevDriveSummaryInformation.xaml.cs => Views/CloneRepoSummaryInformationView.xaml.cs} (62%) diff --git a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj index 7346c9d80..46c7e8dfc 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj +++ b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj @@ -39,19 +39,7 @@ Always - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - + MSBuild:Compile @@ -89,12 +77,8 @@ - - - - - + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs index 6a534625d..719874734 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs @@ -115,9 +115,6 @@ private static IServiceCollection AddSummaryInformation(this IServiceCollection { // View models services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); return services; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index 7297da8ec..2d61784ce 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -254,7 +254,7 @@ IAsyncOperation ISetupTask.Execute() SummaryScreenInformation = _host.GetService(); var fileToUse = configurationFileLocations.OrderBy(x => File.GetLastWriteTime(x)).FirstOrDefault(); - (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).FileName = fileToUse; + (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).FilePathAndName = fileToUse; (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).RepoName = RepositoryName; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml deleted file mode 100644 index 9a0964e94..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs deleted file mode 100644 index 641d1371a..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/CloneRepoSummaryInformation.xaml.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; -using Windows.Foundation; -using Windows.Foundation.Collections; - -namespace DevHome.SetupFlow.Templates; - -/// -/// An empty page that can be used on its own or navigated to within a Frame. -/// -public sealed partial class CloneRepoSummaryInformation : ResourceDictionary -{ - public CloneRepoSummaryInformation() - { - this.InitializeComponent(); - } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml deleted file mode 100644 index 383e43cf9..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs deleted file mode 100644 index 167d4c77a..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/ConfigurationSummaryInformation.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; -using Windows.Foundation; -using Windows.Foundation.Collections; - -namespace DevHome.SetupFlow.Templates; - -public sealed partial class ConfigurationSummaryInformation : ResourceDictionary -{ - public ConfigurationSummaryInformation() - { - this.InitializeComponent(); - } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml deleted file mode 100644 index 255738a25..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml deleted file mode 100644 index a05cba9e5..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs deleted file mode 100644 index 6870989f1..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/EmptySummaryInformation.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; -using Windows.Foundation; -using Windows.Foundation.Collections; - -namespace DevHome.SetupFlow.Templates; - -public sealed partial class EmptySummaryInformation : ResourceDictionary -{ - public EmptySummaryInformation() - { - this.InitializeComponent(); - } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml b/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml deleted file mode 100644 index 8f8c24b09..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs deleted file mode 100644 index ae71a2690..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/InstallPackageSummaryInformation.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; -using Windows.Foundation; -using Windows.Foundation.Collections; - -namespace DevHome.SetupFlow.Templates; - -public sealed partial class InstallPackageSummaryInformation : ResourceDictionary -{ - public InstallPackageSummaryInformation() - { - this.InitializeComponent(); - } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs b/tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs deleted file mode 100644 index e860abcf5..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/SummaryInformationTemplateSelector.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.SetupFlow.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.SetupFlow.Templates; - -public class SummaryInformationTemplateSelector : DataTemplateSelector -{ - public DataTemplate CloneRepoDataTemplate - { - get; set; - } - - public DataTemplate ConfigurationDataTemplate - { - get; set; - } - - public DataTemplate CreateDevDriveDataTemplate - { - get; set; - } - - public DataTemplate InstallPackageDataTemplate - { - get; set; - } - - public DataTemplate EmptyDataTemplate - { - get; set; - } - - protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) - { - return item switch - { - CloneRepoSummaryInformationViewModel => CloneRepoDataTemplate, - ConfigurationSummaryInformationViewModel => ConfigurationDataTemplate, - CreateDevDriveSummaryInformationViewModel => CreateDevDriveDataTemplate, - InstallPackageSummaryInformationViewModel => InstallPackageDataTemplate, - _ => EmptyDataTemplate, - }; - } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs index e70d54336..84848a7fe 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs @@ -1,15 +1,35 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Diagnostics; +using System.IO; using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Microsoft.Extensions.Hosting; +using Windows.Storage.Pickers; +using WinUIEx; namespace DevHome.SetupFlow.ViewModels; public partial class CloneRepoSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel { + public string FileName => Path.GetFileName(FilePathAndName); + + public bool HasContent => !string.IsNullOrEmpty(FilePathAndName) && !string.IsNullOrEmpty(RepoName); + [ObservableProperty] - private string _fileName; + private string _filePathAndName; [ObservableProperty] private string _repoName; + + [RelayCommand] + public void OpenFileInExplorer() + { + var processStartInfo = new ProcessStartInfo(); + processStartInfo.UseShellExecute = true; + processStartInfo.FileName = Path.GetDirectoryName(FilePathAndName); + + Process.Start(processStartInfo); + } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs index d9753e167..45cbde1c2 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ConfigurationSummaryInformationViewModel.cs @@ -7,4 +7,5 @@ namespace DevHome.SetupFlow.ViewModels; public partial class ConfigurationSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel { + public bool HasContent => false; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs index 50fac1ad7..4b8aeba0d 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CreateDevDriveSummaryInformationViewModel.cs @@ -12,4 +12,5 @@ namespace DevHome.SetupFlow.ViewModels; public partial class CreateDevDriveSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel { + public bool HasContent => false; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs index dde1eaa52..35e58f94f 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/EmptySummaryInformationViewModel.cs @@ -7,4 +7,5 @@ namespace DevHome.SetupFlow.ViewModels; public partial class EmptySummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel { + public bool HasContent => false; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs index 7cf73b42c..465caced5 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs @@ -5,4 +5,5 @@ namespace DevHome.SetupFlow.ViewModels; public interface ISummaryInformationViewModel { + public bool HasContent { get; } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs index 4602c9570..c294db1df 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/InstallPackageSummaryInformationViewModel.cs @@ -7,4 +7,5 @@ namespace DevHome.SetupFlow.ViewModels; public partial class InstallPackageSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel { + public bool HasContent => false; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs index c411f8a26..e3a8e0692 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs @@ -456,11 +456,6 @@ private async Task StartTaskAndReportResult(WinUIEx.WindowEx window, TaskInforma window.DispatcherQueue.TryEnqueue(() => { - if (taskInformation.TaskToExecute.SummaryScreenInformation != null) - { - SummaryInformation.Add(taskInformation.TaskToExecute.SummaryScreenInformation); - } - // Keep decrement inside TryEnqueue to encorce "locking" _numberOfExecutingTasks--; ChangeMessage(taskInformation, loadingMessage, taskFinishedState); diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs index ebb309ce7..f67caa442 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs @@ -19,9 +19,11 @@ using DevHome.SetupFlow.Models; using DevHome.SetupFlow.Services; using DevHome.SetupFlow.TaskGroups; +using DevHome.SetupFlow.Views; using DevHome.Telemetry; using Microsoft.Extensions.Hosting; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media.Imaging; using Windows.System; @@ -49,6 +51,9 @@ public partial class SummaryViewModel : SetupPageViewModelBase [ObservableProperty] private Visibility _showRestartNeeded; + [ObservableProperty] + private ObservableCollection _nextSteps; + [RelayCommand] public async Task ShowLogFiles() { @@ -191,6 +196,7 @@ public SummaryViewModel( _configurationUnitResults = new(GetConfigurationUnitResults); _showRestartNeeded = Visibility.Collapsed; _appManagementInitializer = appManagementInitializer; + _nextSteps = new(); IsNavigationBarVisible = true; IsStepPage = false; @@ -206,7 +212,26 @@ protected async override Task OnFirstNavigateToAsync() if (flowPage is LoadingViewModel loadingViewModel) { failedTasks = loadingViewModel.FailedTasks; - SummaryInformation = loadingViewModel.SummaryInformation; + } + } + + var taskGroups = Orchestrator.TaskGroups; + foreach (var taskGroup in taskGroups) + { + var setupTasks = taskGroup.SetupTasks; + foreach (var setupTask in setupTasks) + { + if (setupTask.SummaryScreenInformation.HasContent) + { + switch (setupTask) + { + case CloneRepoTask: + var configResult = new CloneRepoSummaryInformationView(); + configResult.DataContext = setupTask.SummaryScreenInformation; + NextSteps.Add(configResult); + break; + } + } } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml new file mode 100644 index 000000000..5029cef73 --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml.cs similarity index 62% rename from tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml.cs rename to tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml.cs index 9dbaf1de9..03a69cd71 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Templates/CreateDevDriveSummaryInformation.xaml.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; +using DevHome.SetupFlow.ViewModels; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; @@ -16,11 +17,13 @@ using Windows.Foundation; using Windows.Foundation.Collections; -namespace DevHome.SetupFlow.Templates; +namespace DevHome.SetupFlow.Views; -public sealed partial class CreateDevDriveSummaryInformation : ResourceDictionary +public sealed partial class CloneRepoSummaryInformationView : UserControl { - public CreateDevDriveSummaryInformation() + public CloneRepoSummaryInformationViewModel ViewModel => (CloneRepoSummaryInformationViewModel)this.DataContext; + + public CloneRepoSummaryInformationView() { this.InitializeComponent(); } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml index 8c86b5001..da4d5e761 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml @@ -6,7 +6,6 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:converters="using:CommunityToolkit.WinUI.Converters" xmlns:viewModels="using:DevHome.SetupFlow.ViewModels" - xmlns:templates="using:DevHome.SetupFlow.Templates" xmlns:i="using:Microsoft.Xaml.Interactivity" xmlns:ic="using:Microsoft.Xaml.Interactions.Core" xmlns:models="using:DevHome.SetupFlow.Models" @@ -49,11 +48,6 @@ - - - - - @@ -182,22 +176,6 @@ - - - - - - - - - - @@ -215,7 +193,7 @@ - + @@ -280,7 +258,7 @@ HorizontalAlignment="Stretch" Padding="0,15,0,30" BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}" - BorderThickness="{ThemeResource TopNavigationViewContentGridBorderThickness}"> + BorderThickness="0, 1, 0, 2"> @@ -335,7 +313,20 @@ Margin="0, 50, 0, 0"/> - + + + + + + + + + + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs index eff984525..2c4298b4c 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Collections.Generic; +using DevHome.SetupFlow.Models; using DevHome.SetupFlow.ViewModels; using DevHome.SetupFlow.Windows; using Microsoft.UI.Xaml; @@ -9,7 +11,9 @@ namespace DevHome.SetupFlow.Views; public sealed partial class SummaryView : UserControl -{ +{ + private readonly List _nextSteps = new(); + public SummaryView() { this.InitializeComponent(); From 3b75e0dd748cfc4b79b3981d48e2146f1514ab94 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Thu, 14 Mar 2024 10:14:09 -0700 Subject: [PATCH 04/17] Fixing some UI --- .../SummaryPage/CloneRepoNextStepError.cs | 37 +++++ .../SummaryPage/CloneRepoNextStepEvent.cs | 30 ++++ .../SummaryPage/CloneRepoNextStepsEvent.cs | 32 ++++ .../DevHome.SetupFlow/Models/CloneRepoTask.cs | 31 ++-- ...loneRepoSummaryInformationFileViewModel.cs | 138 ++++++++++++++++-- .../ISummaryInformationViewModel.cs | 6 + .../ViewModels/SummaryViewModel.cs | 27 +++- .../CloneRepoSummaryInformationView.xaml | 6 +- 8 files changed, 274 insertions(+), 33 deletions(-) create mode 100644 common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs create mode 100644 common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepEvent.cs create mode 100644 common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepsEvent.cs diff --git a/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs new file mode 100644 index 000000000..f563aab06 --- /dev/null +++ b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DevHome.Telemetry; +using Microsoft.Diagnostics.Telemetry.Internal; + +namespace DevHome.Common.TelemetryEvents.SetupFlow.SummaryPage; + +[EventData] +public class CloneRepoNextStepError : EventBase +{ + public string Operation { get; } + + public Exception Error { get; } + + public string RepoName { get; } + + public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance; + + public CloneRepoNextStepError(string operation, Exception exception, string repoName) + { + Operation = operation; + Error = exception; + RepoName = repoName; + } + + public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) + { + // no op + } +} diff --git a/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepEvent.cs b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepEvent.cs new file mode 100644 index 000000000..6d0017592 --- /dev/null +++ b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepEvent.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.Tracing; +using DevHome.Telemetry; +using Microsoft.Diagnostics.Telemetry.Internal; + +namespace DevHome.Common.TelemetryEvents.SetupFlow.SummaryPage; + +[EventData] +public class CloneRepoNextStepEvent : EventBase +{ + public string Operation { get; } + + public string RepoName { get; } + + public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance; + + public CloneRepoNextStepEvent(string operation, string repoName) + { + Operation = operation; + RepoName = repoName; + } + + public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) + { + // no op + } +} diff --git a/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepsEvent.cs b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepsEvent.cs new file mode 100644 index 000000000..5882d8d48 --- /dev/null +++ b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepsEvent.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DevHome.Telemetry; +using Microsoft.Diagnostics.Telemetry; +using Microsoft.Diagnostics.Telemetry.Internal; + +namespace DevHome.Common.TelemetryEvents.SetupFlow.SummaryPage; + +[EventData] +public class CloneRepoNextStepsEvent : EventBase +{ + public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServicePerformance; + + public int NumberOfConfigurationFilesFound { get; } + + public CloneRepoNextStepsEvent(int numberOfConfigurationFilesFound) + { + NumberOfConfigurationFilesFound = numberOfConfigurationFilesFound; + } + + public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) + { + // No op. + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index 2d61784ce..34491633d 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -32,6 +32,12 @@ namespace DevHome.SetupFlow.Models; /// public partial class CloneRepoTask : ObservableObject, ISetupTask { + private const string _configurationFileName = ".configurations"; + + private const string _configurationFileYamlExtension = ".dsc.yaml"; + + private const string _configurationFileWingetExtension = ".winget"; + private readonly IHost _host; private readonly Guid _activityId; @@ -238,24 +244,23 @@ IAsyncOperation ISetupTask.Execute() return TaskFinishedState.Failure; } - var configurationFileLocations = new List(); + SummaryScreenInformation = _host.GetService(); - var configurationDirectory = Path.Join(_cloneLocation.FullName, ".configurations"); + // Search for a configuration file. + var configurationDirectory = Path.Join(_cloneLocation.FullName, _configurationFileName); if (Directory.Exists(configurationDirectory)) { - foreach (var configurationFile in Directory.EnumerateFiles(configurationDirectory)) + var fileToUse = Directory.EnumerateFiles(configurationDirectory) + .Where(file => file.EndsWith(_configurationFileYamlExtension, StringComparison.OrdinalIgnoreCase) || + file.EndsWith(_configurationFileWingetExtension, StringComparison.OrdinalIgnoreCase)) + .OrderBy(configurationFile => File.GetLastWriteTime(configurationFile)) + .FirstOrDefault(); + + if (fileToUse != null) { - if (configurationFile.EndsWith(".dsc.yaml", StringComparison.OrdinalIgnoreCase) || - configurationFile.EndsWith(".winget", StringComparison.OrdinalIgnoreCase)) - { - configurationFileLocations.Add(configurationFile); - } + (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).FilePathAndName = fileToUse; + (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).RepoName = RepositoryName; } - - SummaryScreenInformation = _host.GetService(); - var fileToUse = configurationFileLocations.OrderBy(x => File.GetLastWriteTime(x)).FirstOrDefault(); - (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).FilePathAndName = fileToUse; - (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).RepoName = RepositoryName; } WasCloningSuccessful = true; diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs index 84848a7fe..f0d4f7b7f 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs @@ -1,35 +1,151 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; +using System.ComponentModel; using System.Diagnostics; using System.IO; -using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using DevHome.Common.Extensions; +using DevHome.Common.TelemetryEvents.SetupFlow.SummaryPage; +using DevHome.Logging; +using DevHome.SetupFlow.Services; +using DevHome.Telemetry; using Microsoft.Extensions.Hosting; -using Windows.Storage.Pickers; -using WinUIEx; namespace DevHome.SetupFlow.ViewModels; -public partial class CloneRepoSummaryInformationViewModel : ObservableRecipient, ISummaryInformationViewModel +public partial class CloneRepoSummaryInformationViewModel : ISummaryInformationViewModel { - public string FileName => Path.GetFileName(FilePathAndName); + private const string _eventName = "CloneRepo_NextSteps_Event"; + + private const string _runOperation = "run"; + + private const string _viewOperation = "view"; + + private readonly Guid _relatedActivityId; + + public string FileName + { + get + { + var fileName = Path.GetFileName(FilePathAndName); + + if (fileName is not null) + { + return fileName; + } + else + { + return string.Empty; + } + } + } public bool HasContent => !string.IsNullOrEmpty(FilePathAndName) && !string.IsNullOrEmpty(RepoName); - [ObservableProperty] - private string _filePathAndName; + public string FilePathAndName { get; set; } = string.Empty; - [ObservableProperty] - private string _repoName; + public string RepoName { get; set; } = string.Empty; + + public CloneRepoSummaryInformationViewModel(IHost host) + { + _relatedActivityId = host.GetService().ActivityId; + } [RelayCommand] public void OpenFileInExplorer() { + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepEvent(_viewOperation, RepoName), _relatedActivityId); + + if (FilePathAndName is null) + { + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName)), RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is null when trying to view file."); + return; + } + + if (string.IsNullOrEmpty(FilePathAndName)) + { + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, new ArgumentException($"{nameof(FilePathAndName)} is empty."), RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is empty when trying to view file."); + return; + } + + var processStartInfo = new ProcessStartInfo(); + processStartInfo.UseShellExecute = true; + + try + { + processStartInfo.FileName = Path.GetDirectoryName(FilePathAndName); + } + catch (PathTooLongException ex) + { + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, ex, RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is too long."); + return; + } + + StartProcess(processStartInfo, _viewOperation); + } + + [RelayCommand] + public void RunInAdminCommandPrompt() + { + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepEvent(_runOperation, RepoName), _relatedActivityId); + + if (FileName is null) + { + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_runOperation, new ArgumentNullException(nameof(FileName)), RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + return; + } + + if (FilePathAndName is null) + { + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_runOperation, new ArgumentException(nameof(FileName)), RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + return; + } + var processStartInfo = new ProcessStartInfo(); processStartInfo.UseShellExecute = true; - processStartInfo.FileName = Path.GetDirectoryName(FilePathAndName); + processStartInfo.FileName = "winget"; + processStartInfo.ArgumentList.Add("configure"); + processStartInfo.ArgumentList.Add(FilePathAndName); + processStartInfo.Verb = "RunAs"; + + StartProcess(processStartInfo, _runOperation); + } + + private void StartProcess(ProcessStartInfo processStartInfo, string operation) + { + if (processStartInfo is null) + { + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, new ArgumentNullException(nameof(processStartInfo)), RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(Process)} is null. Operation {operation}"); + return; + } - Process.Start(processStartInfo); + try + { + Process.Start(processStartInfo); + } + catch (Win32Exception win32Exception) + { + // Usually because the UAC prompt was declined. + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, win32Exception, RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", win32Exception); + } + catch (ObjectDisposedException objectDisposedException) + { + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, objectDisposedException, RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportError($"THe process object was disposed before it could start. Operation {operation}", objectDisposedException); + } + catch (InvalidOperationException invalidOperationException) + { + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, invalidOperationException, RepoName), _relatedActivityId); + GlobalLog.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", invalidOperationException); + } } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs index 465caced5..a60bcbce1 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ISummaryInformationViewModel.cs @@ -1,9 +1,15 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; + namespace DevHome.SetupFlow.ViewModels; public interface ISummaryInformationViewModel { + /// + /// Gets a value indicating whether this object has enough data to be used + /// in the next steps portion of the summary screen. + /// public bool HasContent { get; } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs index f67caa442..4c72669ff 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs @@ -12,6 +12,7 @@ using DevHome.Common.Extensions; using DevHome.Common.Services; using DevHome.Common.TelemetryEvents.SetupFlow; +using DevHome.Common.TelemetryEvents.SetupFlow.SummaryPage; using DevHome.Contracts.Services; using DevHome.Dashboard.ViewModels; using DevHome.Settings.ViewModels; @@ -42,6 +43,10 @@ public partial class SummaryViewModel : SetupPageViewModelBase private readonly PackageProvider _packageProvider; private readonly IAppManagementInitializer _appManagementInitializer; + private readonly List _cloneRepoNextSteps; + + public List NextSteps => _cloneRepoNextSteps; + [ObservableProperty] private ObservableCollection _summaryInformation; @@ -51,9 +56,6 @@ public partial class SummaryViewModel : SetupPageViewModelBase [ObservableProperty] private Visibility _showRestartNeeded; - [ObservableProperty] - private ObservableCollection _nextSteps; - [RelayCommand] public async Task ShowLogFiles() { @@ -196,7 +198,7 @@ public SummaryViewModel( _configurationUnitResults = new(GetConfigurationUnitResults); _showRestartNeeded = Visibility.Collapsed; _appManagementInitializer = appManagementInitializer; - _nextSteps = new(); + _cloneRepoNextSteps = new(); IsNavigationBarVisible = true; IsStepPage = false; @@ -215,26 +217,31 @@ protected async override Task OnFirstNavigateToAsync() } } + // Collect all next steps. var taskGroups = Orchestrator.TaskGroups; foreach (var taskGroup in taskGroups) { var setupTasks = taskGroup.SetupTasks; foreach (var setupTask in setupTasks) { - if (setupTask.SummaryScreenInformation.HasContent) + if (setupTask.SummaryScreenInformation is not null && + setupTask.SummaryScreenInformation.HasContent) { switch (setupTask) { case CloneRepoTask: var configResult = new CloneRepoSummaryInformationView(); configResult.DataContext = setupTask.SummaryScreenInformation; - NextSteps.Add(configResult); + _cloneRepoNextSteps.Add(configResult); break; } } } } + // Send telemetry about the number of next steps tasks found broken down by their type. + ReportSummaryTaskCounts(); + BitmapImage statusSymbol; if (_host.GetService().Theme == ElementTheme.Dark) { @@ -263,6 +270,14 @@ protected async override Task OnFirstNavigateToAsync() await ReloadCatalogsAsync(); } + /// + /// Send telemetry about all next steps. + /// + private void ReportSummaryTaskCounts() + { + TelemetryFactory.Get().Log("Summary_NextSteps_Event", LogLevel.Critical, new CloneRepoNextStepsEvent(_cloneRepoNextSteps.Count), Orchestrator.ActivityId); + } + private async Task ReloadCatalogsAsync() { // After installing packages, reconnect to catalogs to diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml index 5029cef73..9cf6516ee 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml @@ -23,17 +23,17 @@ - + - + - + From c08cc92100333a076670ef43287a56e317f0f6ab Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Fri, 15 Mar 2024 14:46:59 -0700 Subject: [PATCH 05/17] Stretching the contents. Adding owning account name --- .../SummaryPage/CloneRepoNextStepError.cs | 10 +-- .../DevHome.SetupFlow/Models/CloneRepoTask.cs | 1 + .../Models/ConfigureTargetTask.cs | 7 +- .../DevHome.SetupFlow/Models/ISetupTask.cs | 4 -- ...loneRepoSummaryInformationFileViewModel.cs | 24 ++++--- .../CloneRepoSummaryInformationView.xaml | 4 +- .../DevHome.SetupFlow/Views/SummaryView.xaml | 68 +++++++++---------- 7 files changed, 59 insertions(+), 59 deletions(-) diff --git a/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs index f563aab06..dfa87c6a6 100644 --- a/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs +++ b/common/TelemetryEvents/SetupFlow/SummaryPage/CloneRepoNextStepError.cs @@ -2,11 +2,7 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using System.Diagnostics.Tracing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using DevHome.Telemetry; using Microsoft.Diagnostics.Telemetry.Internal; @@ -17,16 +13,16 @@ public class CloneRepoNextStepError : EventBase { public string Operation { get; } - public Exception Error { get; } + public string ErrorMessage { get; } public string RepoName { get; } public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance; - public CloneRepoNextStepError(string operation, Exception exception, string repoName) + public CloneRepoNextStepError(string operation, string errorMessage, string repoName) { Operation = operation; - Error = exception; + ErrorMessage = errorMessage; RepoName = repoName; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index fb18a23a0..a78c2edbe 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -263,6 +263,7 @@ IAsyncOperation ISetupTask.Execute() { (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).FilePathAndName = fileToUse; (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).RepoName = RepositoryName; + (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).OwningAccount = RepositoryToClone.OwningAccountName ?? string.Empty; } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs index 25cb50a49..f35660f7d 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs @@ -23,6 +23,7 @@ using DevHome.SetupFlow.Exceptions; using DevHome.SetupFlow.Models.WingetConfigure; using DevHome.SetupFlow.Services; +using DevHome.SetupFlow.ViewModels; using LibGit2Sharp; using Microsoft.UI.Xaml; using Microsoft.Windows.DevHome.SDK; @@ -98,8 +99,10 @@ public class ConfigureTargetTask : ISetupTask /// public SDKApplyConfigurationResult Result { get; private set; } - public IAsyncOperation ApplyConfigurationAsyncOperation { get; private set; } - + public IAsyncOperation ApplyConfigurationAsyncOperation { get; private set; } + + public ISummaryInformationViewModel SummaryScreenInformation => throw new NotImplementedException(); + public ConfigureTargetTask( ISetupFlowStringResource stringResource, IComputeSystemManager computeSystemManager, diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs index 7ad8428c8..7fc8c9715 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs @@ -4,10 +4,6 @@ extern alias Projection; using DevHome.SetupFlow.ViewModels; -using System; -using DevHome.Common.Views; -using DevHome.SetupFlow.ViewModels; -using Microsoft.Windows.DevHome.SDK; using Projection::DevHome.SetupFlow.ElevatedComponent; using Windows.Foundation; diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs index f0d4f7b7f..94d614778 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs @@ -42,12 +42,16 @@ public string FileName } } - public bool HasContent => !string.IsNullOrEmpty(FilePathAndName) && !string.IsNullOrEmpty(RepoName); + public bool HasContent => !string.IsNullOrEmpty(FilePathAndName) + && !string.IsNullOrEmpty(RepoName) + && !string.IsNullOrEmpty(OwningAccount); public string FilePathAndName { get; set; } = string.Empty; public string RepoName { get; set; } = string.Empty; + public string OwningAccount { get; set; } = string.Empty; + public CloneRepoSummaryInformationViewModel(IHost host) { _relatedActivityId = host.GetService().ActivityId; @@ -60,14 +64,14 @@ public void OpenFileInExplorer() if (FilePathAndName is null) { - TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName)), RepoName), _relatedActivityId); + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName)).ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is null when trying to view file."); return; } if (string.IsNullOrEmpty(FilePathAndName)) { - TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, new ArgumentException($"{nameof(FilePathAndName)} is empty."), RepoName), _relatedActivityId); + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, new ArgumentException($"{nameof(FilePathAndName)} is empty.").ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is empty when trying to view file."); return; } @@ -81,7 +85,7 @@ public void OpenFileInExplorer() } catch (PathTooLongException ex) { - TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, ex, RepoName), _relatedActivityId); + TelemetryFactory.Get().Log(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_viewOperation, ex.ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is too long."); return; } @@ -96,14 +100,14 @@ public void RunInAdminCommandPrompt() if (FileName is null) { - TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_runOperation, new ArgumentNullException(nameof(FileName)), RepoName), _relatedActivityId); + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_runOperation, new ArgumentNullException(nameof(FileName)).ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); return; } if (FilePathAndName is null) { - TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_runOperation, new ArgumentException(nameof(FileName)), RepoName), _relatedActivityId); + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(_runOperation, new ArgumentException(nameof(FileName)).ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); return; } @@ -122,7 +126,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) { if (processStartInfo is null) { - TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, new ArgumentNullException(nameof(processStartInfo)), RepoName), _relatedActivityId); + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, new ArgumentNullException(nameof(processStartInfo)).ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(Process)} is null. Operation {operation}"); return; } @@ -134,17 +138,17 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) catch (Win32Exception win32Exception) { // Usually because the UAC prompt was declined. - TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, win32Exception, RepoName), _relatedActivityId); + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, win32Exception.ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", win32Exception); } catch (ObjectDisposedException objectDisposedException) { - TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, objectDisposedException, RepoName), _relatedActivityId); + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, objectDisposedException.ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportError($"THe process object was disposed before it could start. Operation {operation}", objectDisposedException); } catch (InvalidOperationException invalidOperationException) { - TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, invalidOperationException, RepoName), _relatedActivityId); + TelemetryFactory.Get().LogError(_eventName, LogLevel.Critical, new CloneRepoNextStepError(operation, invalidOperationException.ToString(), RepoName), _relatedActivityId); GlobalLog.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", invalidOperationException); } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml index 9cf6516ee..e28d2b529 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/CloneRepoSummaryInformationView.xaml @@ -20,10 +20,12 @@ + + - + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml index da4d5e761..8c7061298 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml @@ -27,7 +27,7 @@ - + + 0, 1, 0, 2 @@ -119,7 +120,7 @@ - + @@ -206,7 +207,7 @@ HorizontalAlignment="Stretch" Padding="0,15,0,30" BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}" - BorderThickness="0, 1, 0, 2"> + BorderThickness="{ThemeResource TopLeftQuadrantThickness}"> @@ -260,7 +261,7 @@ HorizontalAlignment="Stretch" Padding="0,15,0,30" BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}" - BorderThickness="0, 1, 0, 2"> + BorderThickness="{ThemeResource TopLeftQuadrantThickness}"> diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs index b19033484..c89feb8d8 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Collections.Generic; -using DevHome.SetupFlow.Models; using DevHome.SetupFlow.ViewModels; using DevHome.SetupFlow.Windows; using Microsoft.UI.Xaml; From af7b2ae19e0233e7f3da01dd64cddee096f26130 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Tue, 26 Mar 2024 10:45:59 -0700 Subject: [PATCH 14/17] Adding another catch. Removing IHost --- ...loneRepoSummaryInformationFileViewModel.cs | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs index 2e0a660aa..a5eac2681 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs @@ -4,16 +4,13 @@ using System; using System.ComponentModel; using System.Diagnostics; -using System.Drawing; -using System.Globalization; using System.IO; using CommunityToolkit.Mvvm.Input; -using DevHome.Common.Extensions; using DevHome.Common.TelemetryEvents.SetupFlow.SummaryPage; using DevHome.Logging; +using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Services; using DevHome.Telemetry; -using Microsoft.Extensions.Hosting; namespace DevHome.SetupFlow.ViewModels; @@ -60,10 +57,10 @@ public string FileDescription public string RunFileMessage { get; } = string.Empty; - public CloneRepoSummaryInformationViewModel(IHost host) + public CloneRepoSummaryInformationViewModel(SetupFlowOrchestrator setupFlowOrchestrator, ISetupFlowStringResource stringResource) { - _relatedActivityId = host.GetService().ActivityId; - _stringResource = host.GetService(); + _relatedActivityId = setupFlowOrchestrator.ActivityId; + _stringResource = stringResource; FileFoundMessage = _stringResource.GetLocalized(StringResourceKey.CloneRepoNextStepsFileFound); ViewFileMessage = _stringResource.GetLocalized(StringResourceKey.CloneRepoNextStepsView); RunFileMessage = _stringResource.GetLocalized(StringResourceKey.CloneRepoNextStepsRun); @@ -86,7 +83,7 @@ public void OpenFileInExplorer() new CloneRepoNextStepError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName)).ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is null when trying to view file."); + Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is null when trying to view file."); return; } @@ -98,7 +95,7 @@ public void OpenFileInExplorer() new CloneRepoNextStepError(_viewOperation, new ArgumentException($"{nameof(FilePathAndName)} is empty.").ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is empty when trying to view file."); + Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is empty when trying to view file."); return; } @@ -109,6 +106,17 @@ public void OpenFileInExplorer() { processStartInfo.FileName = Path.GetDirectoryName(FilePathAndName); } + catch (ArgumentException ex) + { + TelemetryFactory.Get().Log( + _eventName, + LogLevel.Critical, + new CloneRepoNextStepError(_viewOperation, ex.ToString(), RepoName), + _relatedActivityId); + + Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is either empty, contains only white spaces, or contains invalid characters."); + return; + } catch (PathTooLongException ex) { TelemetryFactory.Get().Log( @@ -117,7 +125,7 @@ public void OpenFileInExplorer() new CloneRepoNextStepError(_viewOperation, ex.ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is too long."); + Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is too long."); return; } @@ -141,7 +149,7 @@ public void RunInAdminCommandPrompt() new CloneRepoNextStepError(_runOperation, new ArgumentNullException(nameof(FileName)).ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); return; } @@ -153,7 +161,7 @@ public void RunInAdminCommandPrompt() new CloneRepoNextStepError(_runOperation, new ArgumentException(nameof(FileName)).ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); return; } @@ -177,7 +185,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, new ArgumentNullException(nameof(processStartInfo)).ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(Process)} is null. Operation {operation}"); + Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(Process)} is null. Operation {operation}"); return; } @@ -194,7 +202,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, win32Exception.ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", win32Exception); + Log.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", win32Exception); } catch (ObjectDisposedException objectDisposedException) { @@ -204,7 +212,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, objectDisposedException.ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportError($"The process object was disposed before it could start. Operation {operation}", objectDisposedException); + Log.Logger?.ReportError($"The process object was disposed before it could start. Operation {operation}", objectDisposedException); } catch (InvalidOperationException invalidOperationException) { @@ -214,7 +222,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, invalidOperationException.ToString(), RepoName), _relatedActivityId); - GlobalLog.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", invalidOperationException); + Log.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", invalidOperationException); } } } From 1998f8de5a0fa66ea0fed0771f36db12fa625d68 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Wed, 27 Mar 2024 13:10:08 -0700 Subject: [PATCH 15/17] Fixing log and spacing issues --- .../DevHome.SetupFlow/Models/CloneRepoTask.cs | 1 - .../Models/ConfigureTargetTask.cs | 5 ++-- ...loneRepoSummaryInformationFileViewModel.cs | 25 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index 801fc1593..592231f0f 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -31,7 +31,6 @@ namespace DevHome.SetupFlow.Models; /// public partial class CloneRepoTask : ObservableObject, ISetupTask { - private const string _configurationFolderName = ".configurations"; private const string _configurationFileYamlExtension = ".dsc.yaml"; diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs index acfe41da7..9bf851069 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs @@ -17,6 +17,7 @@ using DevHome.SetupFlow.Exceptions; using DevHome.SetupFlow.Models.WingetConfigure; using DevHome.SetupFlow.Services; +using DevHome.SetupFlow.ViewModels; using Microsoft.UI.Xaml; using Microsoft.Windows.DevHome.SDK; using Projection::DevHome.SetupFlow.ElevatedComponent; @@ -93,7 +94,7 @@ public class ConfigureTargetTask : ISetupTask public SDKApplyConfigurationResult Result { get; private set; } public IAsyncOperation ApplyConfigurationAsyncOperation { get; private set; } - + public ISummaryInformationViewModel SummaryScreenInformation { get; } public ConfigureTargetTask( @@ -523,4 +524,4 @@ public void UpdateHostConfig() } private void OnThemeChanged(object sender, ElementTheme e) => UpdateHostConfig(); -} \ No newline at end of file +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs index a5eac2681..0a669e7f0 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs @@ -7,15 +7,16 @@ using System.IO; using CommunityToolkit.Mvvm.Input; using DevHome.Common.TelemetryEvents.SetupFlow.SummaryPage; -using DevHome.Logging; -using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Services; using DevHome.Telemetry; +using Serilog; namespace DevHome.SetupFlow.ViewModels; public partial class CloneRepoSummaryInformationViewModel : ISummaryInformationViewModel { + private readonly ILogger _log = Log.ForContext("SourceContext", nameof(CloneRepoSummaryInformationViewModel)); + private const string _eventName = "CloneRepo_NextSteps_Event"; private const string _runOperation = "run"; @@ -83,7 +84,7 @@ public void OpenFileInExplorer() new CloneRepoNextStepError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName)).ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is null when trying to view file."); + _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is null when trying to view file."); return; } @@ -95,7 +96,7 @@ public void OpenFileInExplorer() new CloneRepoNextStepError(_viewOperation, new ArgumentException($"{nameof(FilePathAndName)} is empty.").ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is empty when trying to view file."); + _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is empty when trying to view file."); return; } @@ -114,7 +115,7 @@ public void OpenFileInExplorer() new CloneRepoNextStepError(_viewOperation, ex.ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is either empty, contains only white spaces, or contains invalid characters."); + _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is either empty, contains only white spaces, or contains invalid characters."); return; } catch (PathTooLongException ex) @@ -125,7 +126,7 @@ public void OpenFileInExplorer() new CloneRepoNextStepError(_viewOperation, ex.ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is too long."); + _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is too long."); return; } @@ -149,7 +150,7 @@ public void RunInAdminCommandPrompt() new CloneRepoNextStepError(_runOperation, new ArgumentNullException(nameof(FileName)).ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); return; } @@ -161,7 +162,7 @@ public void RunInAdminCommandPrompt() new CloneRepoNextStepError(_runOperation, new ArgumentException(nameof(FileName)).ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); return; } @@ -185,7 +186,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, new ArgumentNullException(nameof(processStartInfo)).ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportWarn("CloneRepoSummaryInformationViewModel", $"{nameof(Process)} is null. Operation {operation}"); + _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(Process)} is null. Operation {operation}"); return; } @@ -202,7 +203,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, win32Exception.ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", win32Exception); + _log.Warning($"An error happened when starting the process. Operation {operation}", win32Exception); } catch (ObjectDisposedException objectDisposedException) { @@ -212,7 +213,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, objectDisposedException.ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportError($"The process object was disposed before it could start. Operation {operation}", objectDisposedException); + _log.Warning($"The process object was disposed before it could start. Operation {operation}", objectDisposedException); } catch (InvalidOperationException invalidOperationException) { @@ -222,7 +223,7 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) new CloneRepoNextStepError(operation, invalidOperationException.ToString(), RepoName), _relatedActivityId); - Log.Logger?.ReportError($"An error happened when starting the process. Operation {operation}", invalidOperationException); + _log.Warning($"An error happened when starting the process. Operation {operation}", invalidOperationException); } } } From a2f2b2ec635b98af230456f3ce56703cb9dc5de3 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Wed, 27 Mar 2024 13:35:35 -0700 Subject: [PATCH 16/17] Removing extra white-space --- tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs index 27e14d669..2bfe03adf 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs @@ -94,7 +94,7 @@ public class ConfigureTargetTask : ISetupTask public SDKApplyConfigurationResult Result { get; private set; } public IAsyncOperation ApplyConfigurationAsyncOperation { get; private set; } - + public ISummaryInformationViewModel SummaryScreenInformation { get; } public ConfigureTargetTask( From ff737173e7ecb805b811b43e9449fe70602db8d3 Mon Sep 17 00:00:00 2001 From: Darren Hoehna Date: Fri, 29 Mar 2024 13:21:15 -0700 Subject: [PATCH 17/17] Addressing comments. Consolidating exception code --- .../Helpers/DscHelpers.cs | 8 +- .../DevHome.SetupFlow/Models/CloneRepoTask.cs | 34 +++--- .../Strings/en-us/Resources.resw | 2 +- ...loneRepoSummaryInformationFileViewModel.cs | 104 +++++------------- .../ViewModels/SummaryViewModel.cs | 6 +- 5 files changed, 52 insertions(+), 102 deletions(-) diff --git a/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs b/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs index 4519578d2..ed255d617 100644 --- a/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs +++ b/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs @@ -24,5 +24,11 @@ public static class DscHelpers public const string DevHomeHeaderBanner = @"# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2 # Reference: https://github.com/microsoft/winget-create#building-the-client -# WinGet Configure file Generated By Dev Home."; +# WinGet Configure file Generated By Dev Home."; + + public const string ConfigurationFolderName = ".configurations"; + + public const string ConfigurationFileYamlExtension = ".dsc.yaml"; + + public const string ConfigurationFileWingetExtension = ".winget"; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index 6a1c96cd9..0a9e2f085 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -14,6 +14,8 @@ using DevHome.Common.Services; using DevHome.Common.TelemetryEvents; using DevHome.Common.TelemetryEvents.SetupFlow; +using DevHome.SetupFlow.Common; +using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Services; using DevHome.SetupFlow.ViewModels; using DevHome.Telemetry; @@ -31,12 +33,6 @@ namespace DevHome.SetupFlow.Models; /// public partial class CloneRepoTask : ObservableObject, ISetupTask { - private const string _configurationFolderName = ".configurations"; - - private const string _configurationFileYamlExtension = ".dsc.yaml"; - - private const string _configurationFileWingetExtension = ".winget"; - private readonly IHost _host; private readonly ILogger _log = Log.ForContext("SourceContext", nameof(CloneRepoTask)); @@ -143,7 +139,9 @@ public bool DependsOnDevDriveToBeInstalled get; set; } - public ISummaryInformationViewModel SummaryScreenInformation { get; private set; } + private readonly CloneRepoSummaryInformationViewModel _summaryScreenInformation; + + public ISummaryInformationViewModel SummaryScreenInformation => _summaryScreenInformation; /// /// Initializes a new instance of the class. @@ -151,7 +149,7 @@ public bool DependsOnDevDriveToBeInstalled /// Repository will be placed here. at _cloneLocation.FullName /// The repository to clone /// Credentials needed to clone a private repo - public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, IDeveloperId developerId, IStringResource stringResource, string providerName, Guid activityId, IHost host) + public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, IDeveloperId developerId, ISetupFlowStringResource stringResource, string providerName, Guid activityId, IHost host) { _cloneLocation = cloneLocation; this.RepositoryToClone = repositoryToClone; @@ -162,6 +160,7 @@ public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo clone _repositoryProvider = repositoryProvider; _activityId = activityId; _host = host; + _summaryScreenInformation = new CloneRepoSummaryInformationViewModel(host.GetService(), stringResource); } /// @@ -170,7 +169,7 @@ public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo clone /// /// Repository will be placed here, at _cloneLocation.FullName /// The repository to clone - public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, IStringResource stringResource, string providerName, Guid activityId, IHost host) + public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, ISetupFlowStringResource stringResource, string providerName, Guid activityId, IHost host) { _cloneLocation = cloneLocation; this.RepositoryToClone = repositoryToClone; @@ -181,6 +180,7 @@ public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo clone _repositoryProvider = repositoryProvider; _activityId = activityId; _host = host; + _summaryScreenInformation = new CloneRepoSummaryInformationViewModel(host.GetService(), stringResource); } private void SetMessages(IStringResource stringResource) @@ -248,23 +248,21 @@ IAsyncOperation ISetupTask.Execute() return TaskFinishedState.Failure; } - SummaryScreenInformation = _host.GetService(); - // Search for a configuration file. - var configurationDirectory = Path.Join(_cloneLocation.FullName, _configurationFolderName); + var configurationDirectory = Path.Join(_cloneLocation.FullName, DscHelpers.ConfigurationFolderName); if (Directory.Exists(configurationDirectory)) { var fileToUse = Directory.EnumerateFiles(configurationDirectory) - .Where(file => file.EndsWith(_configurationFileYamlExtension, StringComparison.OrdinalIgnoreCase) || - file.EndsWith(_configurationFileWingetExtension, StringComparison.OrdinalIgnoreCase)) - .OrderBy(configurationFile => File.GetLastWriteTime(configurationFile)) + .Where(file => file.EndsWith(DscHelpers.ConfigurationFileYamlExtension, StringComparison.OrdinalIgnoreCase) || + file.EndsWith(DscHelpers.ConfigurationFileWingetExtension, StringComparison.OrdinalIgnoreCase)) + .OrderByDescending(configurationFile => File.GetLastWriteTime(configurationFile)) .FirstOrDefault(); if (fileToUse != null) { - (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).FilePathAndName = fileToUse; - (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).RepoName = RepositoryName; - (SummaryScreenInformation as CloneRepoSummaryInformationViewModel).OwningAccount = RepositoryToClone.OwningAccountName ?? string.Empty; + _summaryScreenInformation.FilePathAndName = fileToUse; + _summaryScreenInformation.RepoName = RepositoryName; + _summaryScreenInformation.OwningAccount = RepositoryToClone.OwningAccountName ?? string.Empty; } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw b/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw index 30aeea2c0..5191c6ae7 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw +++ b/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw @@ -1613,7 +1613,7 @@ Locked={"{0}", "{1}"} Description letting users know what configuration was found and in what repo the file was found in. {0} is the file name with extension. {1} is the repo name including the owner. - Configuration File detected + Configuration file detected Text to notify the user a configuration file was found in a repo. diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs index 0a669e7f0..cf434b518 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/CloneRepoSummaryInformationFileViewModel.cs @@ -78,25 +78,13 @@ public void OpenFileInExplorer() if (FilePathAndName is null) { - TelemetryFactory.Get().Log( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName)).ToString(), RepoName), - _relatedActivityId); - - _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is null when trying to view file."); + SendTelemetryAndLogError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName))); return; } if (string.IsNullOrEmpty(FilePathAndName)) { - TelemetryFactory.Get().Log( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(_viewOperation, new ArgumentException($"{nameof(FilePathAndName)} is empty.").ToString(), RepoName), - _relatedActivityId); - - _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is empty when trying to view file."); + SendTelemetryAndLogError(_viewOperation, new ArgumentNullException(nameof(FilePathAndName))); return; } @@ -105,28 +93,13 @@ public void OpenFileInExplorer() try { + // Not catching PathTooLongException. If the file was in a location that had a too long path, + // the repo, when cloning, would run into a PathTooLongException and repo would not be cloned. processStartInfo.FileName = Path.GetDirectoryName(FilePathAndName); } catch (ArgumentException ex) { - TelemetryFactory.Get().Log( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(_viewOperation, ex.ToString(), RepoName), - _relatedActivityId); - - _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is either empty, contains only white spaces, or contains invalid characters."); - return; - } - catch (PathTooLongException ex) - { - TelemetryFactory.Get().Log( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(_viewOperation, ex.ToString(), RepoName), - _relatedActivityId); - - _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FilePathAndName)} is too long."); + SendTelemetryAndLogError(_viewOperation, ex); return; } @@ -144,25 +117,13 @@ public void RunInAdminCommandPrompt() if (FileName is null) { - TelemetryFactory.Get().LogError( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(_runOperation, new ArgumentNullException(nameof(FileName)).ToString(), RepoName), - _relatedActivityId); - - _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + SendTelemetryAndLogError(_runOperation, new ArgumentNullException(nameof(FileName))); return; } if (FilePathAndName is null) { - TelemetryFactory.Get().LogError( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(_runOperation, new ArgumentException(nameof(FileName)).ToString(), RepoName), - _relatedActivityId); - - _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(FileName)} is null when trying to run file."); + SendTelemetryAndLogError(_runOperation, new ArgumentNullException(nameof(FileName))); return; } @@ -178,18 +139,6 @@ public void RunInAdminCommandPrompt() private void StartProcess(ProcessStartInfo processStartInfo, string operation) { - if (processStartInfo is null) - { - TelemetryFactory.Get().LogError( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(operation, new ArgumentNullException(nameof(processStartInfo)).ToString(), RepoName), - _relatedActivityId); - - _log.Warning("CloneRepoSummaryInformationViewModel", $"{nameof(Process)} is null. Operation {operation}"); - return; - } - try { Process.Start(processStartInfo); @@ -197,33 +146,30 @@ private void StartProcess(ProcessStartInfo processStartInfo, string operation) catch (Win32Exception win32Exception) { // Usually because the UAC prompt was declined. - TelemetryFactory.Get().LogError( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(operation, win32Exception.ToString(), RepoName), - _relatedActivityId); - - _log.Warning($"An error happened when starting the process. Operation {operation}", win32Exception); + SendTelemetryAndLogError(operation, win32Exception); } catch (ObjectDisposedException objectDisposedException) { - TelemetryFactory.Get().LogError( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(operation, objectDisposedException.ToString(), RepoName), - _relatedActivityId); - - _log.Warning($"The process object was disposed before it could start. Operation {operation}", objectDisposedException); + SendTelemetryAndLogError(operation, objectDisposedException); } catch (InvalidOperationException invalidOperationException) { - TelemetryFactory.Get().LogError( - _eventName, - LogLevel.Critical, - new CloneRepoNextStepError(operation, invalidOperationException.ToString(), RepoName), - _relatedActivityId); - - _log.Warning($"An error happened when starting the process. Operation {operation}", invalidOperationException); + SendTelemetryAndLogError(operation, invalidOperationException); } + catch (Exception e) + { + SendTelemetryAndLogError(operation, e); + } + } + + private void SendTelemetryAndLogError(string operation, Exception e) + { + TelemetryFactory.Get().LogError( + _eventName, + LogLevel.Critical, + new CloneRepoNextStepError(operation, e.ToString(), RepoName), + _relatedActivityId); + + _log.Error(e, string.Empty); } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs index d3db4a9a0..d03e2d699 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs @@ -240,7 +240,7 @@ protected async override Task OnFirstNavigateToAsync() } // Send telemetry about the number of next steps tasks found broken down by their type. - ReportSummaryTaskCounts(); + ReportSummaryTaskCounts(_cloneRepoNextSteps.Count); BitmapImage statusSymbol; if (_host.GetService().Theme == ElementTheme.Dark) @@ -273,9 +273,9 @@ protected async override Task OnFirstNavigateToAsync() /// /// Send telemetry about all next steps. /// - private void ReportSummaryTaskCounts() + private void ReportSummaryTaskCounts(int cloneRepoNextStepsCount) { - TelemetryFactory.Get().Log("Summary_NextSteps_Event", LogLevel.Critical, new CloneRepoNextStepsEvent(_cloneRepoNextSteps.Count), Orchestrator.ActivityId); + TelemetryFactory.Get().Log("Summary_NextSteps_Event", LogLevel.Critical, new CloneRepoNextStepsEvent(cloneRepoNextStepsCount), Orchestrator.ActivityId); } private async Task ReloadCatalogsAsync()