Skip to content

Commit

Permalink
Merge pull request #435 from microsoft/staging
Browse files Browse the repository at this point in the history
Release - 8/20/24
EricJohnson327 authored Aug 20, 2024
2 parents 9b013b6 + 1b595b2 commit 24b786f
Showing 47 changed files with 842 additions and 197 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/GitHubExt-CI.yml
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ jobs:
configuration: [Release, Debug]
platform: [x64, x86, arm64]
os: [windows-latest]
dotnet-version: ['6.0.x']
dotnet-version: ['8.0.x']
exclude:
- configuration: Debug
platform: x64
14 changes: 14 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -45,4 +45,18 @@
</PackageReference>
</ItemGroup>

<!-- Needed for reverting back to pre-.NET 8 method of Host using the RID graph to determine assets
This is due to a change in how the RuntimeIdentifier graph was changed in .NET 8. Without this, any assets from
NuGet packages that are targeting win10-* won't get picked up and referenced prooperly. -->
<!-- https://learn.microsoft.com/en-us/dotnet/core/compatibility/deployment/8.0/rid-asset-list -->
<PropertyGroup>
<UseRidGraph>true</UseRidGraph>
</PropertyGroup>
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Runtime.Loader.UseRidGraph" Value="true" />
</ItemGroup>

<PropertyGroup>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
</Project>
2 changes: 2 additions & 0 deletions GitHubExtension.sln
Original file line number Diff line number Diff line change
@@ -49,7 +49,9 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{864DD9CD-9F45-47E8-847F-B72ED182626B}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
exclusion.dic = exclusion.dic
ToolingVersions.props = ToolingVersions.props
EndProjectSection
EndProject
Global
2 changes: 1 addition & 1 deletion ToolingVersions.props
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE-CODE in the project root for license information. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<TargetFramework>net6.0-windows10.0.22000.0</TargetFramework>
<TargetFramework>net8.0-windows10.0.22000.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
</PropertyGroup>
2 changes: 1 addition & 1 deletion build/azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ parameters:
- release

variables:
MSIXVersion: '0.1600'
MSIXVersion: '0.1700'
solution: '**/GitHubExtension.sln'
appxPackageDir: 'AppxPackages'
testOutputArtifactDir: 'TestResults'
64 changes: 3 additions & 61 deletions build/scripts/Build.ps1
Original file line number Diff line number Diff line change
@@ -86,63 +86,22 @@ $ErrorActionPreference = "Stop"
Try {
if (($BuildStep -ieq "all") -Or ($BuildStep -ieq "msix")) {
$buildRing = "Dev"
$newPackageName = $null
$newPackageDisplayName = $null
$newAppDisplayNameResource = $null
$newWidgetProviderDisplayName = $null
$appxmanifestPath = (Join-Path $env:Build_RootDirectory "src\GitHubExtensionServer\Package-Dev.appxmanifest")

if ($AzureBuildingBranch -ieq "release") {
$buildRing = "Stable"
$newPackageName = "Microsoft.Windows.DevHomeGitHubExtension"
$newPackageDisplayName = "Dev Home GitHub Extension (Preview)"
$newAppDisplayNameResource = "ms-resource:AppDisplayNameStable"
$newWidgetProviderDisplayName = "ms-resource:WidgetProviderDisplayNameStable"
$appxmanifestPath = (Join-Path $env:Build_RootDirectory "src\GitHubExtensionServer\Package.appxmanifest")
} elseif ($AzureBuildingBranch -ieq "staging") {
$buildRing = "Canary"
$newPackageName = "Microsoft.Windows.DevHomeGitHubExtension.Canary"
$newPackageDisplayName = "Dev Home GitHub Extension (Canary)"
$newAppDisplayNameResource = "ms-resource:AppDisplayNameCanary"
$newWidgetProviderDisplayName = "ms-resource:WidgetProviderDisplayNameCanary"
$appxmanifestPath = (Join-Path $env:Build_RootDirectory "src\GitHubExtensionServer\Package-Can.appxmanifest")
}

[Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")
$xIdentity = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/foundation/windows10}Identity");
$xProperties = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/foundation/windows10}Properties");
$xDisplayName = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/foundation/windows10}DisplayName");
$xApplications = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/foundation/windows10}Applications");
$xApplication = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/foundation/windows10}Application");
$uapVisualElements = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/uap/windows10}VisualElements");
$xExtensions = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/foundation/windows10}Extensions");
$uapExtension = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/uap/windows10/3}Extension");
$uapAppExtension = [System.Xml.Linq.XName]::Get("{http://schemas.microsoft.com/appx/manifest/uap/windows10/3}AppExtension");

# Update the appxmanifest
$appxmanifestPath = (Join-Path $env:Build_RootDirectory "src\GitHubExtensionServer\Package.appxmanifest")
$appxmanifest = [System.Xml.Linq.XDocument]::Load($appxmanifestPath)
$appxmanifest.Root.Element($xIdentity).Attribute("Version").Value = $env:msix_version
if (-not ([string]::IsNullOrEmpty($newPackageName))) {
$appxmanifest.Root.Element($xIdentity).Attribute("Name").Value = $newPackageName
}
if (-not ([string]::IsNullOrEmpty($newPackageDisplayName))) {
$appxmanifest.Root.Element($xProperties).Element($xDisplayName).Value = $newPackageDisplayName
}
if (-not ([string]::IsNullOrEmpty($newAppDisplayNameResource))) {
$appxmanifest.Root.Element($xApplications).Element($xApplication).Element($uapVisualElements).Attribute("DisplayName").Value = $newAppDisplayNameResource
$extensions = $appxmanifest.Root.Element($xApplications).Element($xApplication).Element($xExtensions).Elements($uapExtension)
foreach ($extension in $extensions) {
if ($extension.Attribute("Category").Value -eq "windows.appExtension") {
$appExtension = $extension.Element($uapAppExtension)
switch ($appExtension.Attribute("Name").Value) {
"com.microsoft.devhome" {
$appExtension.Attribute("DisplayName").Value = $newAppDisplayNameResource
}
"com.microsoft.windows.widgets" {
$appExtension.Attribute("DisplayName").Value = $newWidgetProviderDisplayName
}
}
}
}
}
$appxmanifest.Save($appxmanifestPath)

foreach ($platform in $env:Build_Platform.Split(",")) {
@@ -171,23 +130,6 @@ Try {
# Reset the appxmanifest to prevent unnecessary code changes
$appxmanifest = [System.Xml.Linq.XDocument]::Load($appxmanifestPath)
$appxmanifest.Root.Element($xIdentity).Attribute("Version").Value = "0.0.0.0"
$appxmanifest.Root.Element($xIdentity).Attribute("Name").Value = "Microsoft.Windows.DevHomeGitHubExtension.Dev"
$appxmanifest.Root.Element($xProperties).Element($xDisplayName).Value = "Dev Home GitHub Extension (Dev)"
$appxmanifest.Root.Element($xApplications).Element($xApplication).Element($uapVisualElements).Attribute("DisplayName").Value = "ms-resource:AppDisplayNameDev"
$extensions = $appxmanifest.Root.Element($xApplications).Element($xApplication).Element($xExtensions).Elements($uapExtension)
foreach ($extension in $extensions) {
if ($extension.Attribute("Category").Value -eq "windows.appExtension") {
$appExtension = $extension.Element($uapAppExtension)
switch ($appExtension.Attribute("Name").Value) {
"com.microsoft.devhome" {
$appExtension.Attribute("DisplayName").Value = "ms-resource:AppDisplayNameDev"
}
"com.microsoft.windows.widgets" {
$appExtension.Attribute("DisplayName").Value = "ms-resource:WidgetProviderDisplayNameDev"
}
}
}
}
$appxmanifest.Save($appxmanifestPath)
}

2 changes: 1 addition & 1 deletion build/scripts/CreateBuildInfo.ps1
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ Param(
)

$Major = "0"
$Minor = "16"
$Minor = "17"
$Patch = "99" # default to 99 for local builds

$versionSplit = $Version.Split(".");
2 changes: 1 addition & 1 deletion nuget.config
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
</config>
<packageSources>
<clear />
<add key="DevHomeDependencies" value="https://pkgs.dev.azure.com/ms/DevHome/_packaging/DevHomeDependencies/nuget/v3/index.json" />
<add key="DevHomeDependencies" value="https://pkgs.dev.azure.com/shine-oss/DevHome/_packaging/DevHomeDependencies/nuget/v3/index.json" />
</packageSources>
<disabledPackageSources>
<clear />
2 changes: 1 addition & 1 deletion src/GitHubExtension/Client/Validation.cs
Original file line number Diff line number Diff line change
@@ -213,7 +213,7 @@ private static string AddProtocolToString(string s)

private static string[]? GetNameAndRepoFromFullName(string s)
{
var n = s.Split(new[] { '/' });
var n = s.Split(['/']);

// This should be exactly two results with no empty strings.
if (n.Length != 2 || string.IsNullOrEmpty(n[0]) || string.IsNullOrEmpty(n[1]))
2 changes: 1 addition & 1 deletion src/GitHubExtension/Constants.cs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

namespace GitHubExtension;

internal class Constants
internal sealed class Constants
{
#pragma warning disable SA1310 // Field names should not contain underscore
public const string DEV_HOME_APPLICATION_NAME = "DevHome";
10 changes: 5 additions & 5 deletions src/GitHubExtension/DataManager/GitHubDataManager.cs
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ await UpdateDataForRepositoryAsync(
await UpdatePullRequestsAsync(repository, devId.GitHubClient, parameters.RequestOptions);
});

SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), new string[] { "Issues", "PullRequests" });
SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), ["Issues", "PullRequests"]);
}

public async Task UpdateAllDataForRepositoryAsync(string fullName, RequestOptions? options = null)
@@ -133,7 +133,7 @@ await UpdateDataForRepositoryAsync(
await UpdatePullRequestsAsync(repository, devId.GitHubClient, parameters.RequestOptions);
});

SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), new string[] { "PullRequests" });
SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), ["PullRequests"]);
}

public async Task UpdatePullRequestsForRepositoryAsync(string fullName, RequestOptions? options = null)
@@ -162,7 +162,7 @@ await UpdateDataForRepositoryAsync(
await UpdateIssuesAsync(repository, devId.GitHubClient, parameters.RequestOptions);
});

SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), new string[] { "Issues" });
SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), ["Issues"]);
}

public async Task UpdateIssuesForRepositoryAsync(string fullName, RequestOptions? options = null)
@@ -202,7 +202,7 @@ await UpdateDataForRepositoryAsync(
await UpdateReleasesAsync(repository, devId.GitHubClient, parameters.RequestOptions);
});

SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), new string[] { "Releases" });
SendRepositoryUpdateEvent(this, GetFullNameFromOwnerAndRepository(owner, name), ["Releases"]);
}

public IEnumerable<Repository> GetRepositories()
@@ -788,7 +788,7 @@ private void SetLastUpdatedInMetaData()
// Converts fullName -> owner, name.
private string[] GetOwnerAndRepositoryNameFromFullName(string fullName)
{
var nameSplit = fullName.Split(new[] { '/' });
var nameSplit = fullName.Split(['/']);
if (nameSplit.Length != 2 || string.IsNullOrEmpty(nameSplit[0]) || string.IsNullOrEmpty(nameSplit[1]))
{
_log.Error($"Invalid repository full name: {fullName}");
2 changes: 1 addition & 1 deletion src/GitHubExtension/DataModel/DataObjects/Repository.cs
Original file line number Diff line number Diff line change
@@ -274,7 +274,7 @@ public static IEnumerable<Repository> GetAll(DataStore dataStore)

public static Repository? Get(DataStore dataStore, string fullName)
{
var nameSplit = fullName.Split(new[] { '/' }, 2);
var nameSplit = fullName.Split(['/'], 2);
if (nameSplit.Length != 2)
{
_log.Warning($"Invalid fullName input into Repository.Get: {fullName}");
2 changes: 1 addition & 1 deletion src/GitHubExtension/DeveloperId/LoginUI/EndPage.cs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

namespace GitHubExtension.DeveloperId.LoginUI;

internal class EndPage : LoginUIPage
internal sealed class EndPage : LoginUIPage
{
public EndPage()
: base(LoginUIState.End)
Original file line number Diff line number Diff line change
@@ -6,12 +6,12 @@

namespace GitHubExtension.DeveloperId.LoginUI;

internal class EnterpriseServerPATPage : LoginUIPage
internal sealed class EnterpriseServerPATPage : LoginUIPage
{
public EnterpriseServerPATPage(Uri hostAddress, string errorText, SecureString inputPAT)
: base(LoginUIState.EnterpriseServerPATPage)
{
Data = new PageData()
Data = new EnterpriseServerPATPageData()
{
EnterpriseServerPATPageInputValue = new System.Net.NetworkCredential(string.Empty, inputPAT).Password ?? string.Empty,
EnterpriseServerPATPageErrorValue = errorText ?? string.Empty,
@@ -22,7 +22,7 @@ public EnterpriseServerPATPage(Uri hostAddress, string errorText, SecureString i
};
}

internal class PageData : ILoginUIPageData
internal sealed class EnterpriseServerPATPageData : ILoginUIPageData
{
public string EnterpriseServerPATPageInputValue { get; set; } = string.Empty;

@@ -36,19 +36,19 @@ internal class PageData : ILoginUIPageData

public string GetJson()
{
return Json.Stringify(this);
return Json.Stringify(this, _optionsWithContext);
}
}

internal class ActionPayload : SubmitActionPayload
internal sealed class ActionPayload : SubmitActionPayload
{
public string? URL
{
get; set;
}
}

internal class InputPayload
internal sealed class InputPayload
{
public string? PAT
{
14 changes: 7 additions & 7 deletions src/GitHubExtension/DeveloperId/LoginUI/EnterpriseServerPage.cs
Original file line number Diff line number Diff line change
@@ -5,12 +5,12 @@

namespace GitHubExtension.DeveloperId.LoginUI;

internal class EnterpriseServerPage : LoginUIPage
internal sealed class EnterpriseServerPage : LoginUIPage
{
public EnterpriseServerPage(Uri? hostAddress, string errorText)
: base(LoginUIState.EnterpriseServerPage)
{
Data = new PageData()
Data = new EnterpriseServerPageData()
{
EnterpriseServerInputValue = hostAddress?.ToString() ?? string.Empty,
EnterpriseServerPageErrorValue = errorText ?? string.Empty,
@@ -21,15 +21,15 @@ public EnterpriseServerPage(Uri? hostAddress, string errorText)
public EnterpriseServerPage(string hostAddress, string errorText)
: base(LoginUIState.EnterpriseServerPage)
{
Data = new PageData()
Data = new EnterpriseServerPageData()
{
EnterpriseServerInputValue = hostAddress,
EnterpriseServerPageErrorValue = errorText ?? string.Empty,
EnterpriseServerPageErrorVisible = !string.IsNullOrEmpty(errorText),
};
}

internal class PageData : ILoginUIPageData
internal sealed class EnterpriseServerPageData : ILoginUIPageData
{
public string EnterpriseServerInputValue { get; set; } = string.Empty;

@@ -40,15 +40,15 @@ internal class PageData : ILoginUIPageData

public string GetJson()
{
return Json.Stringify(this);
return Json.Stringify(this, _optionsWithContext);
}
}

internal class ActionPayload : SubmitActionPayload
internal sealed class ActionPayload : SubmitActionPayload
{
}

internal class InputPayload
internal sealed class InputPayload
{
public string? EnterpriseServer
{
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Text.Json.Serialization;
using static GitHubExtension.DeveloperId.LoginUI.EnterpriseServerPage;
using static GitHubExtension.DeveloperId.LoginUI.EnterpriseServerPATPage;
using static GitHubExtension.DeveloperId.LoginUI.LoginFailedPage;
using static GitHubExtension.DeveloperId.LoginUI.LoginPage;
using static GitHubExtension.DeveloperId.LoginUI.LoginSucceededPage;
using static GitHubExtension.DeveloperId.LoginUI.WaitingPage;

namespace GitHubExtension.DeveloperId;

[JsonSerializable(typeof(EnterpriseServerPageData))]
[JsonSerializable(typeof(EnterpriseServerPATPageData))]
[JsonSerializable(typeof(LoginFailedPageData))]
[JsonSerializable(typeof(LoginPageData))]
[JsonSerializable(typeof(LoginSucceededPageData))]
[JsonSerializable(typeof(WaitingPageData))]
internal sealed partial class JsonSourceGenerationContext : JsonSerializerContext
{
}
6 changes: 3 additions & 3 deletions src/GitHubExtension/DeveloperId/LoginUI/LoginFailedPage.cs
Original file line number Diff line number Diff line change
@@ -5,19 +5,19 @@

namespace GitHubExtension.DeveloperId.LoginUI;

internal class LoginFailedPage : LoginUIPage
internal sealed class LoginFailedPage : LoginUIPage
{
public LoginFailedPage()
: base(LoginUIState.LoginFailedPage)
{
Data = new LoginFailedPageData();
}

internal class LoginFailedPageData : ILoginUIPageData
internal sealed class LoginFailedPageData : ILoginUIPageData
{
public string GetJson()
{
return Json.Stringify(this);
return Json.Stringify(this, _optionsWithContext);
}
}
}
10 changes: 5 additions & 5 deletions src/GitHubExtension/DeveloperId/LoginUI/LoginPage.cs
Original file line number Diff line number Diff line change
@@ -5,23 +5,23 @@

namespace GitHubExtension.DeveloperId.LoginUI;

internal class LoginPage : LoginUIPage
internal sealed class LoginPage : LoginUIPage
{
public LoginPage()
: base(LoginUIState.LoginPage)
{
Data = new PageData();
Data = new LoginPageData();
}

internal class PageData : ILoginUIPageData
internal sealed class LoginPageData : ILoginUIPageData
{
public string GetJson()
{
return Json.Stringify(this);
return Json.Stringify(this, _optionsWithContext);
}
}

internal class ActionPayload : SubmitActionPayload
internal sealed class ActionPayload : SubmitActionPayload
{
public bool IsEnterprise()
{
6 changes: 3 additions & 3 deletions src/GitHubExtension/DeveloperId/LoginUI/LoginSucceededPage.cs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@

namespace GitHubExtension.DeveloperId.LoginUI;

internal class LoginSucceededPage : LoginUIPage
internal sealed class LoginSucceededPage : LoginUIPage
{
public LoginSucceededPage(IDeveloperId developerId)
: base(LoginUIState.LoginSucceededPage)
@@ -17,13 +17,13 @@ public LoginSucceededPage(IDeveloperId developerId)
};
}

internal class LoginSucceededPageData : ILoginUIPageData
internal sealed class LoginSucceededPageData : ILoginUIPageData
{
public string? Message { get; set; } = string.Empty;

public string GetJson()
{
return Json.Stringify(this);
return Json.Stringify(this, _optionsWithContext);
}
}
}
15 changes: 11 additions & 4 deletions src/GitHubExtension/DeveloperId/LoginUI/LoginUIPage.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Text.Json;
using System.Text.Json.Serialization;
using GitHubExtension.Helpers;
using Microsoft.Windows.DevHome.SDK;

@@ -12,6 +14,14 @@ internal class LoginUIPage
private readonly LoginUIState _state;
private ILoginUIPageData? _data;

public static readonly JsonSerializerOptions _optionsWithContext = new()
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
IncludeFields = true,
TypeInfoResolver = JsonSourceGenerationContext.Default,
};

public interface ILoginUIPageData
{
public abstract string GetJson();
@@ -31,10 +41,7 @@ public LoginUIPage(LoginUIState state)

public ProviderOperationResult UpdateExtensionAdaptiveCard(IExtensionAdaptiveCard adaptiveCard)
{
if (adaptiveCard == null)
{
throw new ArgumentNullException(nameof(adaptiveCard));
}
ArgumentNullException.ThrowIfNull(adaptiveCard);

return adaptiveCard.Update(_template, _data?.GetJson(), Enum.GetName(typeof(LoginUIState), _state));
}
6 changes: 3 additions & 3 deletions src/GitHubExtension/DeveloperId/LoginUI/WaitingPage.cs
Original file line number Diff line number Diff line change
@@ -5,19 +5,19 @@

namespace GitHubExtension.DeveloperId.LoginUI;

internal class WaitingPage : LoginUIPage
internal sealed class WaitingPage : LoginUIPage
{
public WaitingPage()
: base(LoginUIState.WaitingPage)
{
Data = new WaitingPageData();
}

internal class WaitingPageData : ILoginUIPageData
internal sealed class WaitingPageData : ILoginUIPageData
{
public string GetJson()
{
return Json.Stringify(this);
return Json.Stringify(this, _optionsWithContext);
}
}
}
4 changes: 2 additions & 2 deletions src/GitHubExtension/DeveloperId/OAuthRequest.cs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@

namespace GitHubExtension.DeveloperId;

internal class OAuthRequest : IDisposable
internal sealed class OAuthRequest : IDisposable
{
private static readonly Lazy<ILogger> _logger = new(() => Serilog.Log.ForContext("SourceContext", nameof(OAuthRequest)));

@@ -33,7 +33,7 @@ internal OAuthRequest()
State = string.Empty;
}

protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposing)
{
6 changes: 6 additions & 0 deletions src/GitHubExtension/GitHubExtension.cs
Original file line number Diff line number Diff line change
@@ -10,7 +10,13 @@
namespace GitHubExtension;

[ComVisible(true)]
#if CANARY_BUILD
[Guid("7AB70F8F-3644-495C-B473-A6750AE1D547")]
#elif STABLE_BUILD
[Guid("6B5F1179-B2AE-4D5E-94FC-E5E119D1B8F0")]
#else
[Guid("190B5CB2-BBAC-424E-92F8-98C7C41C1039")]
#endif
[ComDefaultInterface(typeof(IExtension))]
public sealed class GitHubExtension : IExtension
{
2 changes: 1 addition & 1 deletion src/GitHubExtension/Helpers/IconData.cs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

namespace GitHubExtension.Helpers;

internal class IconData
internal sealed class IconData
{
public const string AssignedWidgetTitleIconData =
"iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwS" +
3 changes: 1 addition & 2 deletions src/GitHubExtension/Helpers/IconLoader.cs
Original file line number Diff line number Diff line change
@@ -13,9 +13,8 @@ public static string GetIconAsBase64(string filename)
{
var log = Log.ForContext("SourceContext", nameof(IconLoader));
log.Verbose($"Asking for icon: {filename}");
if (!_base64ImageRegistry.ContainsKey(filename))
if (!_base64ImageRegistry.TryAdd(filename, ConvertIconToDataString(filename)))
{
_base64ImageRegistry.Add(filename, ConvertIconToDataString(filename));
log.Verbose($"The icon {filename} was converted and is now stored.");
}

25 changes: 10 additions & 15 deletions src/GitHubExtension/Helpers/Json.cs
Original file line number Diff line number Diff line change
@@ -9,6 +9,13 @@ namespace GitHubExtension.Helpers;

public static class Json
{
private static readonly JsonSerializerOptions _options = new()
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
IncludeFields = true,
};

public static async Task<T> ToObjectAsync<T>(string value)
{
if (typeof(T) == typeof(bool))
@@ -35,21 +42,14 @@ public static async Task<string> StringifyAsync<T>(T value)
});
}

public static string Stringify<T>(T value)
public static string Stringify<T>(T value, JsonSerializerOptions? options = null)
{
if (typeof(T) == typeof(bool))
{
return value!.ToString()!.ToLowerInvariant();
}

return System.Text.Json.JsonSerializer.Serialize(
value,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
IncludeFields = true,
});
return System.Text.Json.JsonSerializer.Serialize(value, options ?? _options);
}

public static T? ToObject<T>(string json)
@@ -59,11 +59,6 @@ public static string Stringify<T>(T value)
return (T)(object)bool.Parse(json);
}

return System.Text.Json.JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
IncludeFields = true,
});
return System.Text.Json.JsonSerializer.Deserialize<T>(json, _options);
}
}
4 changes: 2 additions & 2 deletions src/GitHubExtension/Helpers/LocalSettings.cs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ public static class LocalSettings
private static readonly string _applicationDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DevHome/ApplicationData");
private static readonly string _localSettingsFile = "LocalSettings.json";

private static IDictionary<string, object>? _settings;
private static Dictionary<string, object>? _settings;

private static async Task InitializeAsync()
{
@@ -23,7 +23,7 @@ private static async Task InitializeAsync()
}
else
{
_settings = await Task.Run(() => FileHelper.Read<IDictionary<string, object>>(_applicationDataFolder, _localSettingsFile)) ?? new Dictionary<string, object>();
_settings = await Task.Run(() => FileHelper.Read<Dictionary<string, object>>(_applicationDataFolder, _localSettingsFile)) ?? new Dictionary<string, object>();
}
}
}
2 changes: 1 addition & 1 deletion src/GitHubExtension/Helpers/TimeSpanHelper.cs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@

namespace GitHubExtension.Helpers;

internal class TimeSpanHelper
internal sealed class TimeSpanHelper
{
public static string TimeSpanToDisplayString(TimeSpan timeSpan, ILogger? log = null)
{
6 changes: 3 additions & 3 deletions src/GitHubExtension/Notifications/NotificationHandler.cs
Original file line number Diff line number Diff line change
@@ -24,13 +24,13 @@ public static void NotificationActivation(AppNotificationActivatedEventArgs args
{
_log.Information($"Notification Activated with args: {NotificationArgsToString(args)}");

if (args.Arguments.ContainsKey("htmlurl"))
if (args.Arguments.TryGetValue("htmlurl", out var htmlUrl))
{
try
{
// Do not assume this string is a safe URL and blindly execute it; verify that it is
// in fact a valid GitHub URL.
var urlString = args.Arguments["htmlurl"];
var urlString = htmlUrl;
if (!Validation.IsValidGitHubURL(urlString))
{
throw new InvalidGitHubUrlException($"{urlString} is invalid.");
@@ -47,7 +47,7 @@ public static void NotificationActivation(AppNotificationActivatedEventArgs args
}
catch (Exception ex)
{
_log.Error(ex, $"Failed launching Uri for {args.Arguments["htmlurl"]}");
_log.Error(ex, $"Failed launching Uri for {htmlUrl}");
}

return;
4 changes: 2 additions & 2 deletions src/GitHubExtension/Providers/SettingsUIController.cs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@

namespace GitHubExtension.Providers;

internal class SettingsUIController : IExtensionAdaptiveCardSession
internal sealed class SettingsUIController : IExtensionAdaptiveCardSession
{
private static readonly Lazy<ILogger> _logger = new(() => Serilog.Log.ForContext("SourceContext", nameof(RepositoryProvider)));

@@ -68,7 +68,7 @@ public IAsyncOperation<ProviderOperationResult> OnAction(string action, string i
}

// Adaptive Card Templates for SettingsUI.
private class SettingsUITemplate
private sealed class SettingsUITemplate
{
internal string GetSettingsUITemplate()
{
4 changes: 1 addition & 3 deletions src/GitHubExtension/Widgets/GitHubAssignedWidget.cs
Original file line number Diff line number Diff line change
@@ -6,10 +6,8 @@

namespace GitHubExtension.Widgets;

internal class GitHubAssignedWidget : GitHubUserWidget
internal sealed class GitHubAssignedWidget : GitHubUserWidget
{
protected static readonly new string Name = nameof(GitHubAssignedWidget);

protected override string GetTitleIconData()
{
return IconData.AssignedWidgetTitleIconData;
2 changes: 1 addition & 1 deletion src/GitHubExtension/Widgets/GitHubIssuesWidget.cs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@

namespace GitHubExtension.Widgets;

internal class GitHubIssuesWidget : GitHubRepositoryWidget
internal sealed class GitHubIssuesWidget : GitHubRepositoryWidget
{
private readonly string _issuesIconData = IconLoader.GetIconAsBase64("issues.png");

2 changes: 1 addition & 1 deletion src/GitHubExtension/Widgets/GitHubMentionedInWidget.cs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@

namespace GitHubExtension.Widgets;

internal class GitHubMentionedInWidget : GitHubUserWidget
internal sealed class GitHubMentionedInWidget : GitHubUserWidget
{
protected override string GetTitleIconData()
{
2 changes: 1 addition & 1 deletion src/GitHubExtension/Widgets/GitHubPullsWidget.cs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@

namespace GitHubExtension.Widgets;

internal class GitHubPullsWidget : GitHubRepositoryWidget
internal sealed class GitHubPullsWidget : GitHubRepositoryWidget
{
private readonly string _pullsIconData = IconLoader.GetIconAsBase64("pulls.png");

4 changes: 2 additions & 2 deletions src/GitHubExtension/Widgets/GitHubReleasesWidget.cs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@

namespace GitHubExtension.Widgets;

internal class GitHubReleasesWidget : GitHubRepositoryWidget
internal sealed class GitHubReleasesWidget : GitHubRepositoryWidget
{
private readonly string _releasesIconData = IconLoader.GetIconAsBase64("releases.png");

@@ -121,7 +121,7 @@ public override void LoadContentData()

releasesData.Add("releases", releasesArray);
releasesData.Add("selected_repo", repository?.FullName ?? string.Empty);
releasesData.Add("widgetTitle", WidgetTitle);
releasesData.Add("widgetTitle", WidgetTitle);
releasesData.Add("is_loading_data", DataState == WidgetDataState.Unknown);
releasesData.Add("releases_icon_data", _releasesIconData);

2 changes: 1 addition & 1 deletion src/GitHubExtension/Widgets/GitHubReviewWidget.cs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@

namespace GitHubExtension.Widgets;

internal class GitHubReviewWidget : GitHubUserWidget
internal sealed class GitHubReviewWidget : GitHubUserWidget
{
public GitHubReviewWidget()
: base()
8 changes: 4 additions & 4 deletions src/GitHubExtension/Widgets/GitHubWidget.cs
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ public override void CreateWidget(WidgetContext widgetContext, string state)

// If there is a state, it is being retrieved from the widget service, so
// this widget was pinned before.
if (state.Any())
if (state.Length != 0)
{
ResetWidgetInfoFromState();
Saved = true;
@@ -207,7 +207,7 @@ public string GetSignIn()

public bool IsUserLoggedIn()
{
IDeveloperIdProvider authProvider = DeveloperIdProvider.GetInstance();
var authProvider = DeveloperIdProvider.GetInstance();
return authProvider.GetLoggedInDeveloperIds().DeveloperIds.Any();
}

@@ -261,10 +261,10 @@ public virtual string GetData(WidgetPageState page)

protected string GetTemplateForPage(WidgetPageState page)
{
if (Template.ContainsKey(page))
if (Template.TryGetValue(page, out var pageTemplate))
{
Log.Debug($"Using cached template for {page}");
return Template[page];
return pageTemplate;
}

try
2 changes: 1 addition & 1 deletion src/GitHubExtension/Widgets/WidgetImplFactory.cs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
namespace GitHubExtension.Widgets;

[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "Templated class")]
internal class WidgetImplFactory<T> : IWidgetImplFactory
internal sealed class WidgetImplFactory<T> : IWidgetImplFactory
where T : WidgetImpl, new()
{
public WidgetImpl Create(WidgetContext widgetContext, string state)
38 changes: 22 additions & 16 deletions src/GitHubExtension/Widgets/WidgetProvider.cs
Original file line number Diff line number Diff line change
@@ -9,7 +9,13 @@ namespace GitHubExtension.Widgets;

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
#if CANARY_BUILD
[Guid("E8778523-0D5F-478F-8AC3-1467928BDEF7")]
#elif STABLE_BUILD
[Guid("F23870B0-B391-4466-84E2-42A991078613")]
#else
[Guid("3AF3462E-0CCE-4200-887B-FB41872A4EFB")]
#endif
public sealed class WidgetProvider : IWidgetProvider, IWidgetProvider2
{
private readonly ILogger _log = Log.ForContext("SourceContext", nameof(WidgetProvider));
@@ -34,11 +40,11 @@ private void InitializeWidget(WidgetContext widgetContext, string state)
var widgetId = widgetContext.Id;
var widgetDefinitionId = widgetContext.DefinitionId;
_log.Verbose($"Calling Initialize for Widget Id: {widgetId} - {widgetDefinitionId}");
if (_widgetDefinitionRegistry.ContainsKey(widgetDefinitionId))
if (_widgetDefinitionRegistry.TryGetValue(widgetDefinitionId, out var widgetDefinition))
{
if (!_runningWidgets.ContainsKey(widgetId))
{
var factory = _widgetDefinitionRegistry[widgetDefinitionId];
var factory = widgetDefinition;
var widgetImpl = factory.Create(widgetContext, state);
_runningWidgets.Add(widgetId, widgetImpl);
}
@@ -93,37 +99,37 @@ public void Activate(WidgetContext widgetContext)
{
_log.Verbose($"Activate id: {widgetContext.Id} definitionId: {widgetContext.DefinitionId}");
var widgetId = widgetContext.Id;
if (_runningWidgets.ContainsKey(widgetId))
if (_runningWidgets.TryGetValue(widgetId, out var widget))
{
_runningWidgets[widgetId].Activate(widgetContext);
widget.Activate(widgetContext);
}
else
{
// Called to activate a widget that we don't know about, which is unexpected. Try to recover by creating it.
_log.Warning($"Found WidgetId that was not known: {widgetContext.Id}, attempting to recover by creating it.");
CreateWidget(widgetContext);
if (_runningWidgets.ContainsKey(widgetId))
if (_runningWidgets.TryGetValue(widgetId, out var newWidget))
{
_runningWidgets[widgetId].Activate(widgetContext);
newWidget.Activate(widgetContext);
}
}
}

public void Deactivate(string widgetId)
{
_log.Verbose($"Deactivate id: {widgetId}");
if (_runningWidgets.ContainsKey(widgetId))
if (_runningWidgets.TryGetValue(widgetId, out var widget))
{
_runningWidgets[widgetId].Deactivate(widgetId);
widget.Deactivate(widgetId);
}
}

public void DeleteWidget(string widgetId, string customState)
{
_log.Information($"DeleteWidget id: {widgetId}");
if (_runningWidgets.ContainsKey(widgetId))
if (_runningWidgets.TryGetValue(widgetId, out var widget))
{
_runningWidgets[widgetId].DeleteWidget(widgetId, customState);
widget.DeleteWidget(widgetId, customState);
_runningWidgets.Remove(widgetId);
}
}
@@ -133,9 +139,9 @@ public void OnActionInvoked(WidgetActionInvokedArgs actionInvokedArgs)
_log.Debug($"OnActionInvoked id: {actionInvokedArgs.WidgetContext.Id} definitionId: {actionInvokedArgs.WidgetContext.DefinitionId}");
var widgetContext = actionInvokedArgs.WidgetContext;
var widgetId = widgetContext.Id;
if (_runningWidgets.ContainsKey(widgetId))
if (_runningWidgets.TryGetValue(widgetId, out var widget))
{
_runningWidgets[widgetId].OnActionInvoked(actionInvokedArgs);
widget.OnActionInvoked(actionInvokedArgs);
}
}

@@ -144,9 +150,9 @@ public void OnCustomizationRequested(WidgetCustomizationRequestedArgs customizat
_log.Debug($"OnCustomizationRequested id: {customizationRequestedArgs.WidgetContext.Id} definitionId: {customizationRequestedArgs.WidgetContext.DefinitionId}");
var widgetContext = customizationRequestedArgs.WidgetContext;
var widgetId = widgetContext.Id;
if (_runningWidgets.ContainsKey(widgetId))
if (_runningWidgets.TryGetValue(widgetId, out var widget))
{
_runningWidgets[widgetId].OnCustomizationRequested(customizationRequestedArgs);
widget.OnCustomizationRequested(customizationRequestedArgs);
}
}

@@ -155,9 +161,9 @@ public void OnWidgetContextChanged(WidgetContextChangedArgs contextChangedArgs)
_log.Debug($"OnWidgetContextChanged id: {contextChangedArgs.WidgetContext.Id} definitionId: {contextChangedArgs.WidgetContext.DefinitionId}");
var widgetContext = contextChangedArgs.WidgetContext;
var widgetId = widgetContext.Id;
if (_runningWidgets.ContainsKey(widgetId))
if (_runningWidgets.TryGetValue(widgetId, out var widget))
{
_runningWidgets[widgetId].OnWidgetContextChanged(contextChangedArgs);
widget.OnWidgetContextChanged(contextChangedArgs);
}
}
}
2 changes: 1 addition & 1 deletion src/GitHubExtension/Widgets/WidgetServer.cs
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ public void Dispose()
}
}

private class Ole32
private sealed class Ole32
{
#pragma warning disable SA1310 // Field names should not contain underscore
// https://docs.microsoft.com/windows/win32/api/wtypesbase/ne-wtypesbase-clsctx
18 changes: 18 additions & 0 deletions src/GitHubExtensionServer/GitHubExtensionServer.csproj
Original file line number Diff line number Diff line change
@@ -44,6 +44,24 @@
<Folder Include="Assets\" />
</ItemGroup>

<ItemGroup Condition="'$(BuildRing)' == 'Dev'">
<AppxManifest Include="Package-Dev.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>

<ItemGroup Condition="'$(BuildRing)' == 'Canary'">
<AppxManifest Include="Package-Can.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>

<ItemGroup Condition="'$(BuildRing)' == 'Stable'">
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Serilog" Version="3.1.1" />
294 changes: 294 additions & 0 deletions src/GitHubExtensionServer/Package-Can.appxmanifest

Large diffs are not rendered by default.

294 changes: 294 additions & 0 deletions src/GitHubExtensionServer/Package-Dev.appxmanifest

Large diffs are not rendered by default.

56 changes: 28 additions & 28 deletions src/GitHubExtensionServer/Package.appxmanifest

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/GitHubExtensionServer/Program.cs
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ namespace GitHubExtension;
public sealed class Program
{
[MTAThread]
public static void Main([System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArray] string[] args)
public static async Task Main([System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArray] string[] args)
{
// Setup Logging
Environment.SetEnvironmentVariable("DEVHOME_LOGS_ROOT", ApplicationData.Current.TemporaryFolder.Path);
@@ -38,7 +38,7 @@ public static void Main([System.Runtime.InteropServices.WindowsRuntime.ReadOnlyA
if (!mainInstance.IsCurrent)
{
Log.Information($"Not main instance, redirecting.");
mainInstance.RedirectActivationToAsync(activationArgs).AsTask().Wait();
await mainInstance.RedirectActivationToAsync(activationArgs);
notificationManager.Unregister();
Log.CloseAndFlush();
return;
@@ -74,7 +74,7 @@ private static void AppActivationRedirected(object? sender, Microsoft.Windows.Ap
var d = activationArgs.Data as ILaunchActivatedEventArgs;
var args = d?.Arguments.Split();

if (args?.Length > 0 && args[1] == "-RegisterProcessAsComServer")
if (args?.Length > 1 && args[1] == "-RegisterProcessAsComServer")
{
Log.Information($"Activation COM Registration Redirect: {string.Join(' ', args.ToList())}");
HandleCOMServerActivation();
48 changes: 48 additions & 0 deletions src/GitHubExtensionServer/Strings/en-us/Resources.resw
Original file line number Diff line number Diff line change
@@ -153,4 +153,52 @@
<value>Releases</value>
<comment>Title for widget that displays the releases of a repository</comment>
</data>
<data name="Widget_Description_AssignedToMe" xml:space="preserve">
<value>List of pull requests and issues assigned to the user in a GitHub repository.</value>
</data>
<data name="Widget_Description_Issues" xml:space="preserve">
<value>List of issues in a GitHub repository.</value>
</data>
<data name="Widget_Description_MentionedIn" xml:space="preserve">
<value>List of issues and pull requests the user is mentioned in in a GitHub repository.</value>
</data>
<data name="Widget_Description_PullRequests" xml:space="preserve">
<value>List of open pull requests in a GitHub repository.</value>
</data>
<data name="Widget_Description_Reviews" xml:space="preserve">
<value>List of pull requests where the user is requested for a review.</value>
</data>
<data name="Widget_DisplayName_AssignedToMe" xml:space="preserve">
<value>Assigned to me</value>
</data>
<data name="Widget_DisplayName_Issues" xml:space="preserve">
<value>Issues</value>
</data>
<data name="Widget_DisplayName_MentionedIn" xml:space="preserve">
<value>Mentioned me</value>
</data>
<data name="Widget_DisplayName_PullRequests" xml:space="preserve">
<value>Pull requests</value>
</data>
<data name="Widget_DisplayName_Reviews" xml:space="preserve">
<value>Review requested</value>
</data>
<data name="Widget_ScreenshotAltDisplay_AssignedToMe" xml:space="preserve">
<value>Assigned To Me widget preview image</value>
</data>
<data name="Widget_ScreenshotAltDisplay_Issues" xml:space="preserve">
<value>Issues widget preview image</value>
</data>
<data name="Widget_ScreenshotAltDisplay_MentionedIn" xml:space="preserve">
<value>Mentioned In widget preview image</value>
</data>
<data name="Widget_ScreenshotAltDisplay_PullRequests" xml:space="preserve">
<value>Pull Requests widget preview image</value>
</data>
<data name="Widget_ScreenshotAltDisplay_Releases" xml:space="preserve">
<value>Releases widget preview image</value>
</data>
<data name="Widget_ScreenshotAltDisplay_Reviews" xml:space="preserve">
<value>Review Requested widget preview image</value>
</data>
</root>
2 changes: 1 addition & 1 deletion src/Telemetry/Logger.cs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@

namespace GitHubExtension.Telemetry;

internal class Logger : ILogger
internal sealed class Logger : ILogger
{
private const string ProviderName = "Microsoft.GitHubExtension";

0 comments on commit 24b786f

Please sign in to comment.