diff --git a/Quarrel.sln b/Quarrel.sln index 6e2e7bd90..52a5f3a27 100644 --- a/Quarrel.sln +++ b/Quarrel.sln @@ -36,6 +36,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quarrel.RichPresence", "src EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quarrel.Samples.RichPresence", "samples\Quarrel.Samples.RichPresence\Quarrel.Samples.RichPresence.csproj", "{4304E7AB-92E3-4313-AD8B-EFDCB033C0CE}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Testing", "Testing", "{E3BFEBEE-5570-4885-B4C7-2CB3E7B04C60}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quarrel.Testing.DirtyServices", "tests\Quarrel.Testing.DirtyServices\Quarrel.Testing.DirtyServices.csproj", "{8BD6BF36-6ECD-4103-B064-1CAE37E954F2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Alpha|Any CPU = Alpha|Any CPU @@ -444,6 +448,46 @@ Global {4304E7AB-92E3-4313-AD8B-EFDCB033C0CE}.Release|ARM64.ActiveCfg = Debug|ARM64 {4304E7AB-92E3-4313-AD8B-EFDCB033C0CE}.Release|x64.ActiveCfg = Debug|x64 {4304E7AB-92E3-4313-AD8B-EFDCB033C0CE}.Release|x86.ActiveCfg = Debug|x86 + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|Any CPU.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|Any CPU.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|ARM.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|ARM.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|ARM64.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|ARM64.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|x64.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|x64.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|x86.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Alpha|x86.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|ARM.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|ARM.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|ARM64.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|x64.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|x64.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|x86.ActiveCfg = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Debug|x86.Build.0 = Debug|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|Any CPU.ActiveCfg = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|Any CPU.Build.0 = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|ARM.ActiveCfg = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|ARM.Build.0 = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|ARM64.ActiveCfg = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|ARM64.Build.0 = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|x64.ActiveCfg = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|x64.Build.0 = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|x86.ActiveCfg = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Insider|x86.Build.0 = Insider|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|Any CPU.Build.0 = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|ARM.ActiveCfg = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|ARM.Build.0 = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|ARM64.ActiveCfg = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|ARM64.Build.0 = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|x64.ActiveCfg = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|x64.Build.0 = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|x86.ActiveCfg = Release|Any CPU + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -456,6 +500,7 @@ Global {7B631D3A-F353-4557-B848-A68140341F53} = {29E0E840-B85F-4209-933B-8369DB2EA187} {BA8BE893-2B4D-4213-A4AF-53AA28BF2E46} = {7B631D3A-F353-4557-B848-A68140341F53} {4304E7AB-92E3-4313-AD8B-EFDCB033C0CE} = {7B631D3A-F353-4557-B848-A68140341F53} + {8BD6BF36-6ECD-4103-B064-1CAE37E954F2} = {E3BFEBEE-5570-4885-B4C7-2CB3E7B04C60} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2B4323A3-5C28-4929-AB1C-20CE992D6024} diff --git a/azure-pipelines-package-alpha.yml b/azure-pipelines-package-alpha.yml index ee8beecaf..1c40154bb 100644 --- a/azure-pipelines-package-alpha.yml +++ b/azure-pipelines-package-alpha.yml @@ -22,7 +22,7 @@ pool: variables: solution: '**/Quarrel.App.sln' - buildPlatform: 'x86|x64|arm|arm64' + buildPlatform: 'x86|x64|arm' buildConfiguration: 'Alpha' installerDirectory: './QuarrelInstaller' appxPackageDir: '$(build.artifactStagingDirectory)\AppxPackages\\' @@ -53,7 +53,7 @@ steps: displayName: Place AppCenterToken inputs: targetType: 'inline' - script: 'Copy-Item $Env:APP_CENTER_TOKEN_PATH -Destination "$($Env:BUILD_SOURCESDIRECTORY)/src/Quarrel/Assets/Tokens/AppCenter/"' + script: 'Copy-Item $Env:APP_CENTER_TOKEN_PATH -Destination "$($Env:BUILD_SOURCESDIRECTORY)/Quarrel/src/Quarrel/Assets/Tokens/AppCenter/"' env: APP_CENTER_TOKEN_PATH: $(appCenterToken.secureFilePath) @@ -80,29 +80,28 @@ steps: /p:PackageCertificateKeyFile="$(signingCertificate.secureFilePath)" /p:PackageCertificateThumbprint="$(SignedCertificateThumbprint-Alpha)" /p:PackageCertificatePassword="$(SignCertificatePassword-Alpha)" - /p:AppInstallerUri="${siteUri}" + /p:AppInstallerUri="$(siteUri)" /p:AppInstallerUpdateFrequency=1 - /p:AppInstallerCheckForUpdateFrequency=OnApplicationRun' + /p:AppInstallerCheckForUpdateFrequency=OnApplicationRun + /p:GenerateAppInstallerFile=true' - powershell: | [Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") $doc = [System.Xml.Linq.XDocument]::Load( "$(appxPackageDir)/Quarrel.appinstaller") - $xName = "{http://schemas.microsoft.com/appx/appinstaller/2017/2}MainBundle" - $bundle = $doc.Root.Element($xName).Attribute("Uri").Value.Replace("${siteUri}", ""); - Copy-Item $bundle -Destination ($(build.artifactStagingDirectory) + $bundle.Replace("/", "_")); + $xName = "{http://schemas.microsoft.com/appx/appinstaller/2017/2}MainBundle"; + $bundle = $doc.Root.Element($xName).Attribute("Uri").Value.Replace("$(siteUri)", ""); + + Copy-Item "$(appxPackageDir)\$($bundle)" -Destination "$(build.artifactStagingDirectory)\$($bundle.Replace("/", "_"))"; $doc.Root.Element($xName).Attribute("Uri").Value = - "https://github.com/UWPCommunity/Quarrel/releases/download/alpha-v$(Build.BuildNumber)/Quarrel.appinstaller" + - $bundle.Replace("/", "_"); + "https://github.com/UWPCommunity/Quarrel/releases/download/alpha-v$(Build.BuildNumber)/$($bundle.Replace("/", "_"))"; - $xName = "{http://schemas.microsoft.com/appx/appinstaller/2017/2}Dependencies" - - foreach ($element in $doc.Root.Elements($xName)){ - $dep = $element.Attribute("Uri").Value.Replace("${siteUri}", ""); - Copy-Item $dep -Destination ($(build.artifactStagingDirectory) + $dep.Replace("/", "_")); + $xName = "{http://schemas.microsoft.com/appx/appinstaller/2017/2}Dependencies"; + foreach ($element in $doc.Root.Element($xName).Elements()){ + $dep = $element.Attribute("Uri").Value.Replace("$(siteUri)", ""); + Copy-Item "$(appxPackageDir)\$($dep)" -Destination "$(build.artifactStagingDirectory)\$($dep.Replace("/", "_"))"; $element.Attribute("Uri").Value = - "https://github.com/UWPCommunity/Quarrel/releases/download/alpha-v$(Build.BuildNumber)/Quarrel.appinstaller" + - $dep.Replace("/", "_"); + "https://github.com/UWPCommunity/Quarrel/releases/download/alpha-v$(Build.BuildNumber)/$($dep.Replace("/", "_"))"; } $doc.Save("$(appInstaller)") displayName: 'Fix appinstaller' @@ -121,14 +120,8 @@ steps: changeLogCompareToRelease: 'lastFullRelease' changeLogType: 'commitBased' assets: | - '$(build.artifactStagingDirectory)/*' - -- task: CopyFiles@2 - displayName: Copy artifacts to QuarrelInstaller repo - inputs: - SourceFolder: '$(build.artifactStagingDirectory)' - Contents: '**' - TargetFolder: '$(installerDirectory)' + $(build.artifactStagingDirectory)\*.msixbundle + $(build.artifactStagingDirectory)\*.appx - script: | git config --global user.email $(GitHub-Email) diff --git a/src/Quarrel.ViewModels/Extensions/Microsoft.Extensions.DependencyInjection/ServiceCollectionExtensions.cs b/src/Quarrel.ViewModels/Extensions/Microsoft.Extensions.DependencyInjection/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..e7fc9cbe9 --- /dev/null +++ b/src/Quarrel.ViewModels/Extensions/Microsoft.Extensions.DependencyInjection/ServiceCollectionExtensions.cs @@ -0,0 +1,23 @@ +// Quarrel © 2022 + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// A class containing extensions for the class. + /// + public static class ServiceCollectionExtensions + { + /// + /// Replaces the service a singleton service in the . + /// + public static void OverrideSingleton(this ServiceCollection services) + where TService : class + where TOldImpl : class, TService + where TNewImpl : class, TService + { + var oldDesc = ServiceDescriptor.Singleton(); + services.Remove(oldDesc); + services.AddSingleton(); + } + } +} diff --git a/src/Quarrel.ViewModels/Services/APIs/GitHubService/GitHubService.cs b/src/Quarrel.ViewModels/Services/APIs/GitHubService/GitHubService.cs index b28d6055e..64eb22dd7 100644 --- a/src/Quarrel.ViewModels/Services/APIs/GitHubService/GitHubService.cs +++ b/src/Quarrel.ViewModels/Services/APIs/GitHubService/GitHubService.cs @@ -64,12 +64,19 @@ public GitHubService(IAnalyticsService analyticsService) return result; } - + /// - public async Task GetDeveloper(Contributor contributor) + public async Task GetDeveloper(Contributor contributor) { - var user = await _gitHubApiService.GetUserAsync(contributor.Name); - return new BindableDeveloper(user, contributor); + try + { + var user = await _gitHubApiService.GetUserAsync(contributor.Name); + return new BindableDeveloper(user, contributor); + } + catch + { + return null; + } } } } diff --git a/src/Quarrel.ViewModels/Services/APIs/GitHubService/IGitHubService.cs b/src/Quarrel.ViewModels/Services/APIs/GitHubService/IGitHubService.cs index 03f8e0c63..ad1d170f9 100644 --- a/src/Quarrel.ViewModels/Services/APIs/GitHubService/IGitHubService.cs +++ b/src/Quarrel.ViewModels/Services/APIs/GitHubService/IGitHubService.cs @@ -22,6 +22,6 @@ public interface IGitHubService /// /// The contributor to get the a full profile for. /// - Task GetDeveloper(Contributor contributor); + Task GetDeveloper(Contributor contributor); } } diff --git a/src/Quarrel/App.Services.cs b/src/Quarrel/App.Services.cs new file mode 100644 index 000000000..c67a66c25 --- /dev/null +++ b/src/Quarrel/App.Services.cs @@ -0,0 +1,79 @@ +// Quarrel © 2022 + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Toolkit.Mvvm.Messaging; +using OwlCore.AbstractStorage; +using Quarrel.Services.Analytics; +using Quarrel.Services.APIs.GitHubService; +using Quarrel.Services.Discord; +using Quarrel.Services.Dispatcher; +using Quarrel.Services.Localization; +using Quarrel.Services.Storage; +using Quarrel.Services.Storage.Models; +using Quarrel.Services.Versioning; +using Quarrel.Services.Windows; +using Quarrel.ViewModels; +using Quarrel.ViewModels.Panels; +using Quarrel.ViewModels.SubPages; +using Quarrel.ViewModels.SubPages.DiscordStatus; +using Quarrel.ViewModels.SubPages.Host; +using Quarrel.ViewModels.SubPages.Meta; +using System; +using Windows.Storage; + +namespace Quarrel +{ + partial class App + { + private IServiceProvider ConfigureServices() + { + IFolderData appDataFolder = new FolderData(ApplicationData.Current.LocalFolder); + + // Register Services + var services = new ServiceCollection(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(new StorageService(appDataFolder, JsonAsyncSerializer.Singleton)); + services.AddSingleton(); + + // Other APIs + services.AddTransient(); + + #if DEV + services.AddSingleton(); + #else + services.AddSingleton(); + #endif + + // ViewModels + services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + // SubPages + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + #if DEV + ApplyDitryOverrides(services); + #endif + + return services.BuildServiceProvider(); + } + + #if DEV + private void ApplyDitryOverrides(ServiceCollection services) + { + // Fill with dirty service overrides for stress testing. + } + #endif + } +} diff --git a/src/Quarrel/App.xaml.cs b/src/Quarrel/App.xaml.cs index a2f592430..b8a67e7cb 100644 --- a/src/Quarrel/App.xaml.cs +++ b/src/Quarrel/App.xaml.cs @@ -3,29 +3,13 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Toolkit.Mvvm.DependencyInjection; using Microsoft.Toolkit.Mvvm.Messaging; -using OwlCore.AbstractStorage; using Quarrel.Controls.Host; using Quarrel.Helpers.LaunchArgs.Models; using Quarrel.Messages; -using Quarrel.Services.Analytics; -using Quarrel.Services.APIs.GitHubService; -using Quarrel.Services.Discord; -using Quarrel.Services.Dispatcher; using Quarrel.Services.Localization; -using Quarrel.Services.Storage; -using Quarrel.Services.Storage.Models; -using Quarrel.Services.Versioning; -using Quarrel.Services.Windows; -using Quarrel.ViewModels; -using Quarrel.ViewModels.Panels; -using Quarrel.ViewModels.SubPages; -using Quarrel.ViewModels.SubPages.DiscordStatus; -using Quarrel.ViewModels.SubPages.Host; -using Quarrel.ViewModels.SubPages.Meta; using System; using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.AppService; -using Windows.Storage; using Windows.UI.Xaml; namespace Quarrel @@ -122,45 +106,5 @@ private void InitializeUI() ILocalizationService localizationService = Services.GetRequiredService(); root.FlowDirection = localizationService.IsRightToLeftLanguage ? FlowDirection.RightToLeft : FlowDirection.LeftToRight; } - - private IServiceProvider ConfigureServices() - { - IFolderData appDataFolder = new FolderData(ApplicationData.Current.LocalFolder); - - // Register Services - var services = new ServiceCollection(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(new StorageService(appDataFolder, JsonAsyncSerializer.Singleton)); - services.AddSingleton(); - - // Other APIs - services.AddTransient(); - - #if DEV - services.AddSingleton(); - #else - services.AddSingleton(); - #endif - - // ViewModels - services.AddSingleton(); - services.AddSingleton(); - services.AddTransient(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - // SubPages - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - return services.BuildServiceProvider(); - } } } diff --git a/src/Quarrel/Quarrel.csproj b/src/Quarrel/Quarrel.csproj index 058a52fd7..564774a8f 100644 --- a/src/Quarrel/Quarrel.csproj +++ b/src/Quarrel/Quarrel.csproj @@ -21,7 +21,6 @@ true False true - true false true Always @@ -42,10 +41,10 @@ full - false + true ALPHA pdbonly - false + true true @@ -82,6 +81,7 @@ + App.xaml @@ -601,6 +601,12 @@ Quarrel.ViewModels + + + {8bd6bf36-6ecd-4103-b064-1cae37e954f2} + Quarrel.Testing.DirtyServices + + @@ -610,6 +616,9 @@ + + + diff --git a/tests/Quarrel.Testing.DirtyServices/APIs/DirtyGitHubService.cs b/tests/Quarrel.Testing.DirtyServices/APIs/DirtyGitHubService.cs new file mode 100644 index 000000000..0dcc9bda2 --- /dev/null +++ b/tests/Quarrel.Testing.DirtyServices/APIs/DirtyGitHubService.cs @@ -0,0 +1,30 @@ +// Quarrel © 2022 + +using GitHub.API.Models; +using Quarrel.Services.APIs.GitHubService; +using Quarrel.Services.APIs.GitHubService.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Quarrel.Testing.DirtyServices.APIs +{ + /// + /// A dirty implementation of the . + /// + public class DirtyGitHubService : IGitHubService + { + /// + public async Task?> GetContributors() + { + await Task.Run(() => {}); + return null; + } + + /// + public async Task GetDeveloper(Contributor contributor) + { + await Task.Run(() => {}); + return null; + } + } +} diff --git a/tests/Quarrel.Testing.DirtyServices/Quarrel.Testing.DirtyServices.csproj b/tests/Quarrel.Testing.DirtyServices/Quarrel.Testing.DirtyServices.csproj new file mode 100644 index 000000000..d91cedb39 --- /dev/null +++ b/tests/Quarrel.Testing.DirtyServices/Quarrel.Testing.DirtyServices.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + +