mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-17 13:55:02 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c64830c5b6 | ||
|
|
561c7cf7b1 | ||
|
|
2c6862de41 | ||
|
|
69842cbadf | ||
|
|
c7327e7bb2 | ||
|
|
de33ed7fc4 | ||
|
|
c99bb8d074 | ||
|
|
a98e54ebc6 | ||
|
|
a832aa1925 | ||
|
|
c7eb5debcb |
@@ -53,12 +53,12 @@ jobs:
|
||||
echo "${{ env.Changelog }}"
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.1
|
||||
uses: microsoft/setup-msbuild@v1.1.3
|
||||
|
||||
- name: Setup project secrets
|
||||
run: |
|
||||
|
||||
@@ -36,12 +36,12 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.1
|
||||
uses: microsoft/setup-msbuild@v1.1.3
|
||||
|
||||
- name: Execute Unit Tests
|
||||
run: dotnet test $env:Test_Project_Path
|
||||
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.x'
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.7.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0-preview-20220726-02" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.9.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -39,5 +39,7 @@ namespace Daybreak.Configuration
|
||||
public bool AutoCheckUpdate { get; set; } = true;
|
||||
[JsonProperty("ProtectedGraphAccessToken")]
|
||||
public string ProtectedGraphAccessToken { get; set; }
|
||||
[JsonProperty("ProtectedGraphRefreshToken")]
|
||||
public string ProtectedGraphRefreshToken { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ using Daybreak.Services.Screens;
|
||||
using Daybreak.Services.Screenshots;
|
||||
using Daybreak.Services.Shortcuts;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.Http.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -28,6 +27,7 @@ using System.Core.Extensions;
|
||||
using Daybreak.Services.Updater.PostUpdate.Actions;
|
||||
using Daybreak.Services.Graph;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Daybreak.Services.Navigation;
|
||||
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
|
||||
@@ -10,11 +10,14 @@
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Line Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
X1="15" X2="26" Y1="11" Y2="0"></Line>
|
||||
X1="15" X2="26" Y1="11" Y2="0"
|
||||
StrokeThickness="2"></Line>
|
||||
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Width="4" Height="4"
|
||||
Width="4" Height="4"
|
||||
StrokeThickness="2"
|
||||
Margin="8,13,13,8"></Ellipse>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
StrokeThickness="2"
|
||||
Data="m15.025,0l-12.7,11.3c-3.1,3.1 -3.1,8.2 0,11.3s8.2,3.1 11.3,0l12.4,-11.6"></Path>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
Width="40"></local:GoldenArrowGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Manage builds"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Clicked="ManageBuildsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FireballGlyph Foreground="White"
|
||||
Width="40"></local:FireballGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Account settings"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
@@ -59,16 +69,6 @@
|
||||
Width="40"></local:ExperimentGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Manage builds"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Clicked="ManageBuildsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FireballGlyph Foreground="White"
|
||||
Width="40"></local:FireballGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Manage client version"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -15,7 +16,6 @@ using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using Utils;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Daybreak</RootNamespace>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
@@ -10,7 +11,7 @@
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
|
||||
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
|
||||
<Version>0.9.7</Version>
|
||||
<Version>0.9.7.3</Version>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<UserSecretsId>cfb2a489-db80-448d-a969-80270f314c46</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
@@ -34,14 +35,14 @@
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LiteDB" Version="5.0.12" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.15" />
|
||||
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1343.22" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1518.46" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="NReco.Logging.File" Version="1.1.5" />
|
||||
<PackageReference Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageReference Include="Slim" Version="1.9.2" />
|
||||
@@ -105,7 +106,7 @@
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
||||
<Exec Command="echo.>$(Version).version" />
|
||||
</Target>
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Screenshots;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Updater.PostUpdate;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Slim;
|
||||
using Slim.Integration.ServiceCollection;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Screenshots;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Views;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Daybreak.Models;
|
||||
|
||||
public sealed class SynchronizationBuild
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string TemplateCode { get; set; }
|
||||
public bool Changed { get; set; }
|
||||
}
|
||||
@@ -3,10 +3,10 @@ using Daybreak.Exceptions;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.Mutex;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Win32;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
@@ -44,7 +44,6 @@ namespace Daybreak.Services.BuildTemplates
|
||||
var emptyBuild = new Build();
|
||||
var name = Guid.NewGuid().ToString();
|
||||
var entry = new BuildEntry { Build = emptyBuild, Name = name, PreviousName = string.Empty };
|
||||
this.SaveBuild(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -52,19 +51,24 @@ namespace Daybreak.Services.BuildTemplates
|
||||
{
|
||||
var emptyBuild = new Build();
|
||||
var entry = new BuildEntry { Build = emptyBuild, Name = name, PreviousName = string.Empty };
|
||||
this.SaveBuild(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void SaveBuild(BuildEntry buildEntry)
|
||||
{
|
||||
var encodedBuild = this.EncodeTemplate(buildEntry.Build);
|
||||
if (string.IsNullOrWhiteSpace(buildEntry.PreviousName))
|
||||
var newPath = Path.Combine(BuildsPath, $"{buildEntry.Name}.txt");
|
||||
if (string.IsNullOrWhiteSpace(buildEntry.PreviousName) is false)
|
||||
{
|
||||
File.Delete($"{BuildsPath}\\{buildEntry.PreviousName}.txt");
|
||||
var oldPath = Path.GetFullPath(Path.Combine(BuildsPath, $"{buildEntry.PreviousName}.txt"));
|
||||
if (File.Exists(oldPath))
|
||||
{
|
||||
File.Delete(oldPath);
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText($"{BuildsPath}\\{buildEntry.Name}.txt", encodedBuild);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(newPath));
|
||||
File.WriteAllText(newPath, encodedBuild);
|
||||
}
|
||||
|
||||
public void RemoveBuild(BuildEntry buildEntry)
|
||||
@@ -82,12 +86,13 @@ namespace Daybreak.Services.BuildTemplates
|
||||
|
||||
public async Task<Result<BuildEntry, Exception>> GetBuild(string name)
|
||||
{
|
||||
if (File.Exists($"{BuildsPath}/{name}.txt") is false)
|
||||
var path = Path.Combine(BuildsPath, $"{name}.txt");
|
||||
if (File.Exists(path) is false)
|
||||
{
|
||||
return new InvalidOperationException("Unable to find build file");
|
||||
}
|
||||
|
||||
var content = await File.ReadAllTextAsync($"{BuildsPath}/{name}.txt");
|
||||
var content = await File.ReadAllTextAsync(path);
|
||||
if (this.TryDecodeTemplate(content, out var build) is false)
|
||||
{
|
||||
return new InvalidOperationException("Unable to parse build file");
|
||||
@@ -98,7 +103,7 @@ namespace Daybreak.Services.BuildTemplates
|
||||
|
||||
public void ClearBuilds()
|
||||
{
|
||||
foreach(var file in Directory.GetFiles(BuildsPath))
|
||||
foreach(var file in Directory.GetFiles(BuildsPath, "*.txt", SearchOption.AllDirectories))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
@@ -106,7 +111,12 @@ namespace Daybreak.Services.BuildTemplates
|
||||
|
||||
public async IAsyncEnumerable<BuildEntry> GetBuilds()
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(BuildsPath))
|
||||
if (Directory.Exists(BuildsPath) is false)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(BuildsPath, "*.txt", SearchOption.AllDirectories))
|
||||
{
|
||||
var maybeBuild = this.DecodeTemplateInner(await File.ReadAllTextAsync(file));
|
||||
var build = maybeBuild.Switch(
|
||||
@@ -119,7 +129,7 @@ namespace Daybreak.Services.BuildTemplates
|
||||
|
||||
if (build is not null)
|
||||
{
|
||||
yield return new BuildEntry { Build = build, Name = Path.GetFileNameWithoutExtension(file), PreviousName = Path.GetFileNameWithoutExtension(file) };
|
||||
yield return new BuildEntry { Build = build, Name = Path.GetRelativePath(BuildsPath, file).Replace(".txt", string.Empty), PreviousName = Path.GetRelativePath(BuildsPath, file).Replace(".txt", string.Empty) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,13 @@ using Daybreak.Controls;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Graph.Models;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
@@ -26,8 +27,8 @@ namespace Daybreak.Services.Graph;
|
||||
|
||||
public sealed class GraphClient : IGraphClient
|
||||
{
|
||||
private const string Scopes = "Files.Read Files.Read.All Files.ReadWrite Files.ReadWrite.All User.Read";
|
||||
private const string RedirectUri = "http://localhost";
|
||||
private const string Scopes = "Files.Read Files.Read.All Files.ReadWrite Files.ReadWrite.All User.Read offline_access";
|
||||
private const string RedirectUri = "http://localhost:42111";
|
||||
|
||||
private const string QueryStateKey = "state";
|
||||
private const string QueryCodeKey = "code";
|
||||
@@ -35,9 +36,11 @@ public sealed class GraphClient : IGraphClient
|
||||
private const string RedirectUriPlaceholder = "[RedirectUri]";
|
||||
private const string ScopesPlaceholder = "[Scopes]";
|
||||
private const string StatePlaceholder = "[State]";
|
||||
private const string RefreshTokenPlaceholder = "[RefreshToken]";
|
||||
private const string ProfileEndpoint = "me";
|
||||
private const string GraphBaseUrl = "https://graph.microsoft.com/v1.0/";
|
||||
private const string TokenUrlPlaceholder = $"https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
|
||||
private const string RefreshTokenUrlPlaceholder = $"https://login.microsoftonline.com/consumers/oauth2/v2.0/token?client_id={ClientIdPlaceholder}&refresh_token={RefreshTokenPlaceholder}";
|
||||
private const string AuthorizationUrlPlaceholder = $"https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id={ClientIdPlaceholder}&response_type=code&redirect_uri={RedirectUriPlaceholder}&response_mode=query&scope={ScopesPlaceholder}&state={StatePlaceholder}";
|
||||
private const string SyncFileUri = $"me/drive/root:/Daybreak/Builds/daybreak.json{ContentSuffix}";
|
||||
private const string ContentSuffix = ":/content";
|
||||
@@ -85,13 +88,22 @@ public sealed class GraphClient : IGraphClient
|
||||
return maybeAccessToken.Switch(
|
||||
onSuccess: token =>
|
||||
{
|
||||
var accessToken = AccessToken.FromTokenResponse(token);
|
||||
this.SaveAccessToken(accessToken);
|
||||
this.SaveTokenResponse(token);
|
||||
return true;
|
||||
},
|
||||
onFailure: exception => exception);
|
||||
}
|
||||
|
||||
public Task<Result<bool, Exception>> LogOut()
|
||||
{
|
||||
this.ResetAccessToken();
|
||||
this.ResetRefreshToken();
|
||||
this.ResetAuthorization();
|
||||
|
||||
//TODO: Currently revoking only one refresh token is not supported. Follow up when MS Graph implements refresh token revocation.
|
||||
return Task.FromResult(Result<bool, Exception>.Success(true));
|
||||
}
|
||||
|
||||
public async Task<Result<User, Exception>> GetUserProfile<TViewType>()
|
||||
where TViewType : UserControl
|
||||
{
|
||||
@@ -104,8 +116,15 @@ public sealed class GraphClient : IGraphClient
|
||||
|
||||
if (DateTime.Now > accessToken.ExpirationDate)
|
||||
{
|
||||
this.viewManager.ShowView<GraphAuthorizationView>(new ViewRedirectContext { CallingView = typeof(TViewType) });
|
||||
return new InvalidOperationException("Client authorization expired");
|
||||
var maybeToken = await this.RefreshAccessToken();
|
||||
if (maybeToken.ExtractValue() is not TokenResponse tokenResponse)
|
||||
{
|
||||
this.viewManager.ShowView<GraphAuthorizationView>(new ViewRedirectContext { CallingView = typeof(TViewType) });
|
||||
return new InvalidOperationException("Client authorization expired");
|
||||
}
|
||||
|
||||
(var newAccessToken, _) = this.SaveTokenResponse(tokenResponse);
|
||||
accessToken = newAccessToken;
|
||||
}
|
||||
|
||||
this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Token);
|
||||
@@ -227,6 +246,30 @@ public sealed class GraphClient : IGraphClient
|
||||
public void ResetAuthorization()
|
||||
{
|
||||
this.ResetAccessToken();
|
||||
this.ResetRefreshToken();
|
||||
}
|
||||
|
||||
private async Task<Optional<TokenResponse>> RefreshAccessToken()
|
||||
{
|
||||
var maybeRefreshToken = this.LoadRefreshToken();
|
||||
if (maybeRefreshToken.ExtractValue() is not RefreshToken refreshToken)
|
||||
{
|
||||
return Optional.None<TokenResponse>();
|
||||
}
|
||||
|
||||
using var httpContent = new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "client_id", ApplicationId },
|
||||
{ "refresh_token", refreshToken.Token },
|
||||
{ "grant_type", "refresh_token" }
|
||||
});
|
||||
using var response = await this.httpClient.PostAsync(TokenUrlPlaceholder, httpContent);
|
||||
if (response.IsSuccessStatusCode is false)
|
||||
{
|
||||
return Optional.None<TokenResponse>();
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
private async Task<bool> PutBuild(BuildEntry buildEntry)
|
||||
@@ -320,7 +363,19 @@ public sealed class GraphClient : IGraphClient
|
||||
.Replace(' ', '+'))
|
||||
.Replace(StatePlaceholder, state);
|
||||
|
||||
while (chromiumBrowserWrapper.Address.StartsWith(RedirectUri) is false)
|
||||
NameValueCollection query = null;
|
||||
bool finished = false;
|
||||
chromiumBrowserWrapper.WebBrowser.CoreWebView2.SourceChanged += (_, sourceArgs) =>
|
||||
{
|
||||
if (chromiumBrowserWrapper.Address.StartsWith(RedirectUri))
|
||||
{
|
||||
query = HttpUtility.ParseQueryString(chromiumBrowserWrapper.Address.Split('?').Skip(1).FirstOrDefault());
|
||||
finished = true;
|
||||
chromiumBrowserWrapper.WebBrowser.CoreWebView2.NavigateToString(string.Empty);
|
||||
}
|
||||
};
|
||||
|
||||
while (finished is false)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -330,8 +385,7 @@ public sealed class GraphClient : IGraphClient
|
||||
await Task.Delay(1000, cancellationToken).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
var query = HttpUtility.ParseQueryString(chromiumBrowserWrapper.Address.Split('?').Skip(1).FirstOrDefault());
|
||||
if (query.GetValues(QueryStateKey) is string[] states is false)
|
||||
if (query?.GetValues(QueryStateKey) is string[] states is false)
|
||||
{
|
||||
throw new InvalidOperationException("Response doesn't have state key in response");
|
||||
}
|
||||
@@ -388,6 +442,16 @@ public sealed class GraphClient : IGraphClient
|
||||
return JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
private (AccessToken, RefreshToken) SaveTokenResponse(TokenResponse token)
|
||||
{
|
||||
var accessToken = AccessToken.FromTokenResponse(token);
|
||||
var refreshToken = RefreshToken.FromTokenResponse(token);
|
||||
this.SaveAccessToken(accessToken);
|
||||
this.SaveRefreshToken(refreshToken);
|
||||
|
||||
return (accessToken, refreshToken);
|
||||
}
|
||||
|
||||
private void ResetAccessToken()
|
||||
{
|
||||
this.liveUpdateableOptions.Value.ProtectedGraphAccessToken = null;
|
||||
@@ -401,6 +465,19 @@ public sealed class GraphClient : IGraphClient
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
}
|
||||
|
||||
private void SaveRefreshToken(RefreshToken refreshToken)
|
||||
{
|
||||
var codeBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(refreshToken));
|
||||
this.liveUpdateableOptions.Value.ProtectedGraphRefreshToken = Convert.ToBase64String(ProtectedData.Protect(codeBytes, Entropy, DataProtectionScope.CurrentUser));
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
}
|
||||
|
||||
private void ResetRefreshToken()
|
||||
{
|
||||
this.liveUpdateableOptions.Value.ProtectedGraphRefreshToken = null;
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
}
|
||||
|
||||
private Optional<AccessToken> LoadAccessToken()
|
||||
{
|
||||
var protectedCode = this.liveUpdateableOptions.Value.ProtectedGraphAccessToken;
|
||||
@@ -422,6 +499,27 @@ public sealed class GraphClient : IGraphClient
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<RefreshToken> LoadRefreshToken()
|
||||
{
|
||||
var protectedCode = this.liveUpdateableOptions.Value.ProtectedGraphRefreshToken;
|
||||
if (protectedCode.IsNullOrWhiteSpace())
|
||||
{
|
||||
return Optional.None<RefreshToken>();
|
||||
}
|
||||
|
||||
var codeBytes = ProtectedData.Unprotect(Convert.FromBase64String(protectedCode), Entropy, DataProtectionScope.CurrentUser);
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<RefreshToken>(Encoding.UTF8.GetString(codeBytes));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.logger.LogError(e, "Failed to load refresh token. Resetting refresh token");
|
||||
this.ResetAccessToken();
|
||||
return Optional.None<RefreshToken>();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetNewState()
|
||||
{
|
||||
return Guid.NewGuid().ToString();
|
||||
|
||||
@@ -14,6 +14,7 @@ public interface IGraphClient
|
||||
Task<Result<User, Exception>> GetUserProfile<TViewType>()
|
||||
where TViewType : UserControl;
|
||||
Task<Result<bool, Exception>> PerformAuthorizationFlow(ChromiumBrowserWrapper chromiumBrowserWrapper, CancellationToken cancellationToken = default);
|
||||
Task<Result<bool, Exception>> LogOut();
|
||||
Task<Result<bool, Exception>> UploadBuilds();
|
||||
Task<Result<bool, Exception>> DownloadBuilds();
|
||||
Task<Result<bool, Exception>> UploadBuild(string buildName);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Daybreak.Services.Graph.Models;
|
||||
|
||||
public sealed class RefreshToken
|
||||
{
|
||||
public string Token { get; set; }
|
||||
|
||||
public static RefreshToken FromTokenResponse(TokenResponse tokenResponse)
|
||||
{
|
||||
return new RefreshToken
|
||||
{
|
||||
Token = tokenResponse.RefreshToken,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.KeyboardHook;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using Daybreak.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Pepa.Wpf.Utilities;
|
||||
using Daybreak.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Services.ViewManagement
|
||||
namespace Daybreak.Services.Navigation
|
||||
{
|
||||
public interface IViewManager : IViewProducer
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Services.ViewManagement
|
||||
namespace Daybreak.Services.Navigation
|
||||
{
|
||||
public interface IViewProducer
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Services.ViewManagement
|
||||
namespace Daybreak.Services.Navigation
|
||||
{
|
||||
public sealed class ViewManager : IViewManager
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Models.Github;
|
||||
using Daybreak.Models.Progress;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Updater.PostUpdate;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Win32;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Daybreak
|
||||
namespace Daybreak.Utils
|
||||
{
|
||||
internal static class EncryptionHelper
|
||||
{
|
||||
|
||||
@@ -3,9 +3,9 @@ using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
|
||||
namespace Pepa.Wpf.Utilities
|
||||
namespace Daybreak.Utils
|
||||
{
|
||||
static class NativeMethods
|
||||
internal static class NativeMethods
|
||||
{
|
||||
public static uint WM_KEYDOWN = 0x0100;
|
||||
public static uint SWP_SHOWWINDOW = 0x0040;
|
||||
@@ -134,4 +134,4 @@ namespace Pepa.Wpf.Utilities
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Utils
|
||||
namespace Daybreak.Utils
|
||||
{
|
||||
public static class StringUtils
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace Utils
|
||||
{
|
||||
for (var i = 1; i < width; i++)
|
||||
{
|
||||
var cost = (s[j - 1] == t[i - 1]) ? 0 : 1;
|
||||
var cost = s[j - 1] == t[i - 1] ? 0 : 1;
|
||||
var insertion = matrix[j, i - 1] + 1;
|
||||
var deletion = matrix[j - 1, i] + 1;
|
||||
var substitution = matrix[j - 1, i - 1] + cost;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Extensions;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Configuration;
|
||||
using System.Extensions;
|
||||
|
||||
@@ -3,7 +3,7 @@ using Daybreak.Controls;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
@@ -20,7 +20,7 @@ namespace Daybreak.Views
|
||||
/// </summary>
|
||||
public partial class BuildTemplateView : UserControl
|
||||
{
|
||||
private const string DisallowedChars = "\r\n\\/.";
|
||||
private const string DisallowedChars = "\r\n/.";
|
||||
|
||||
private bool supressDecode = false;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using Utils;
|
||||
|
||||
namespace Daybreak.Views
|
||||
{
|
||||
@@ -36,7 +36,7 @@ namespace Daybreak.Views
|
||||
private async void LoadBuilds()
|
||||
{
|
||||
this.buildEntries = await this.buildTemplateManager.GetBuilds().ToListAsync();
|
||||
this.BuildEntries.ClearAnd().AddRange(this.buildEntries);
|
||||
this.BuildEntries.ClearAnd().AddRange(this.buildEntries.OrderBy(b => b.Name));
|
||||
}
|
||||
|
||||
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<UserControl.Resources>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" TriggerValue="False"></converters:BooleanToVisibilityConverter>
|
||||
<converters:BooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" TriggerValue="True"></converters:BooleanToVisibilityConverter>
|
||||
<BooleanToVisibilityConverter x:Key="BaseBooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid
|
||||
Background="#A0202020">
|
||||
@@ -25,6 +26,15 @@
|
||||
<controls:BackButton Foreground="White" Height="30" Width="30" Grid.Column="0" HorizontalAlignment="Left" Margin="5"
|
||||
Clicked="BackButton_Clicked" VerticalAlignment="Top"
|
||||
IsEnabled="{Binding ElementName=_this, Path=ButtonsEnabled, Mode=OneWay}"></controls:BackButton>
|
||||
<controls:OpaqueButton Text="Log Out"
|
||||
Foreground="White"
|
||||
Background="DarkGray"
|
||||
HorizontalAlignment="Right"
|
||||
Padding="5"
|
||||
Margin="5"
|
||||
Clicked="LogOutButton_Clicked"
|
||||
Width="80"
|
||||
IsEnabled="{Binding ElementName=_this, Path=ButtonsEnabled, Mode=OneWay}"/>
|
||||
<WrapPanel HorizontalAlignment="Center">
|
||||
<TextBlock
|
||||
Text="Build templates synchronization"
|
||||
@@ -42,7 +52,6 @@
|
||||
Visibility="{Binding ElementName=_this, Path=Synchronized, Mode=OneWay, Converter={StaticResource InverseBooleanToVisibilityConverter}}"/>
|
||||
</Grid>
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel HorizontalAlignment="Center"
|
||||
Grid.Row="1">
|
||||
<TextBlock Text="Logged in as: "
|
||||
@@ -88,9 +97,12 @@
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Rectangle Fill="LawnGreen"
|
||||
Opacity="0.2"
|
||||
Visibility="{Binding Changed, Converter={StaticResource BooleanToVisibilityConverter}}"></Rectangle>
|
||||
<TextBlock FontSize="14"
|
||||
Foreground="White"
|
||||
Text="{Binding Build.Name}"
|
||||
Text="{Binding Name}"
|
||||
HorizontalAlignment="Left"></TextBlock>
|
||||
<TextBlock FontSize="14"
|
||||
Foreground="White"
|
||||
@@ -126,13 +138,16 @@
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Rectangle Fill="Red"
|
||||
Visibility="{Binding Changed, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Opacity="0.2"></Rectangle>
|
||||
<TextBlock FontSize="14"
|
||||
Foreground="White"
|
||||
Text="{Binding TemplateCode}"
|
||||
HorizontalAlignment="Left"></TextBlock>
|
||||
<TextBlock FontSize="14"
|
||||
Foreground="White"
|
||||
Text="{Binding FileName}"
|
||||
Text="{Binding Name}"
|
||||
HorizontalAlignment="Right"></TextBlock>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Core.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Controls;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System.Collections.ObjectModel;
|
||||
using Daybreak.Services.Graph.Models;
|
||||
using System.Extensions;
|
||||
@@ -14,6 +13,7 @@ using Daybreak.Services.BuildTemplates;
|
||||
using System.Linq;
|
||||
using Daybreak.Models;
|
||||
using System.Collections.Generic;
|
||||
using Daybreak.Services.Navigation;
|
||||
|
||||
namespace Daybreak.Views;
|
||||
|
||||
@@ -27,8 +27,8 @@ public partial class BuildsSynchronizationView : UserControl
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly ILogger<BuildsSynchronizationView> logger;
|
||||
|
||||
public ObservableCollection<BuildFile> RemoteBuildEntries { get; } = new();
|
||||
public ObservableCollection<BuildWithTemplateCode> LocalBuildEntries { get; } = new();
|
||||
public ObservableCollection<SynchronizationBuild> RemoteBuildEntries { get; } = new();
|
||||
public ObservableCollection<SynchronizationBuild> LocalBuildEntries { get; } = new();
|
||||
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool buttonsEnabled;
|
||||
@@ -37,9 +37,9 @@ public partial class BuildsSynchronizationView : UserControl
|
||||
[GenerateDependencyProperty]
|
||||
private string lastUploadDate;
|
||||
[GenerateDependencyProperty]
|
||||
private BuildFile selectedRemoteBuild;
|
||||
private SynchronizationBuild selectedRemoteBuild;
|
||||
[GenerateDependencyProperty]
|
||||
private BuildWithTemplateCode selectedLocalBuild;
|
||||
private SynchronizationBuild selectedLocalBuild;
|
||||
[GenerateDependencyProperty]
|
||||
private bool showLoading;
|
||||
[GenerateDependencyProperty]
|
||||
@@ -78,18 +78,28 @@ public partial class BuildsSynchronizationView : UserControl
|
||||
private async Task PopulateBuilds()
|
||||
{
|
||||
var getBuildsResponse = await this.graphClient.RetrieveBuildsList();
|
||||
if (getBuildsResponse.TryExtractSuccess(out var builds) is false)
|
||||
if (getBuildsResponse.TryExtractSuccess(out var remoteBuildFiles) is false)
|
||||
{
|
||||
builds = new List<BuildFile>();
|
||||
remoteBuildFiles = new List<BuildFile>();
|
||||
}
|
||||
|
||||
this.RemoteBuildEntries.ClearAnd().AddRange(builds);
|
||||
var localBuilds = await this.buildTemplateManager.GetBuilds().ToListAsync();
|
||||
this.LocalBuildEntries.ClearAnd().AddRange(localBuilds.Select(build => new BuildWithTemplateCode { Build = build, TemplateCode = this.buildTemplateManager.EncodeTemplate(build.Build) }));
|
||||
var localBuildFiles = await this.buildTemplateManager.GetBuilds().ToListAsync();
|
||||
|
||||
if (this.LocalBuildEntries.Count == this.RemoteBuildEntries.Count &&
|
||||
this.LocalBuildEntries.Select(b => b.Build.Name).Except(this.RemoteBuildEntries.Select(b => b.FileName)).None() &&
|
||||
this.LocalBuildEntries.Select(b => b.TemplateCode).Except(this.RemoteBuildEntries.Select(b => b.TemplateCode)).None())
|
||||
var remoteBuilds = remoteBuildFiles.Select(buildFile => new SynchronizationBuild { Name = buildFile.FileName, TemplateCode = buildFile.TemplateCode })
|
||||
.ToList();
|
||||
var localBuilds = localBuildFiles.Select(build => new SynchronizationBuild { Name = build.Name, TemplateCode = this.buildTemplateManager.EncodeTemplate(build.Build) })
|
||||
.ToList();
|
||||
|
||||
var changedLocalBuilds = localBuilds.Where(
|
||||
localBuild => remoteBuilds.None(remoteBuild => localBuild.Name + localBuild.TemplateCode == remoteBuild.Name + remoteBuild.TemplateCode))
|
||||
.ToList();
|
||||
var changedRemoteBuilds = remoteBuilds.Where(
|
||||
remoteBuild => localBuilds.None(localBuild => localBuild.Name + localBuild.TemplateCode == remoteBuild.Name + remoteBuild.TemplateCode))
|
||||
.ToList();
|
||||
|
||||
if (localBuilds.Any() &&
|
||||
changedLocalBuilds.None() &&
|
||||
changedRemoteBuilds.None())
|
||||
{
|
||||
this.Synchronized = true;
|
||||
}
|
||||
@@ -97,6 +107,14 @@ public partial class BuildsSynchronizationView : UserControl
|
||||
{
|
||||
this.Synchronized = false;
|
||||
}
|
||||
|
||||
foreach(var build in changedLocalBuilds.Concat(changedRemoteBuilds))
|
||||
{
|
||||
build.Changed = true;
|
||||
}
|
||||
|
||||
this.RemoteBuildEntries.ClearAnd().AddRange(remoteBuilds);
|
||||
this.LocalBuildEntries.ClearAnd().AddRange(localBuilds);
|
||||
}
|
||||
|
||||
private void BackButton_Clicked(object sender, EventArgs e)
|
||||
@@ -107,14 +125,14 @@ public partial class BuildsSynchronizationView : UserControl
|
||||
private async void UploadButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
// TODO: Handle failures to upload
|
||||
if (this.SelectedLocalBuild is not BuildWithTemplateCode buildWithTemplateCode)
|
||||
if (this.SelectedLocalBuild is not SynchronizationBuild build)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ButtonsEnabled = false;
|
||||
this.ShowLoading = true;
|
||||
await this.graphClient.UploadBuild(buildWithTemplateCode.Build.Name);
|
||||
await this.graphClient.UploadBuild(build.Name);
|
||||
await this.PopulateBuilds();
|
||||
this.ButtonsEnabled = true;
|
||||
this.ShowLoading = false;
|
||||
@@ -122,14 +140,14 @@ public partial class BuildsSynchronizationView : UserControl
|
||||
|
||||
private async void DownloadButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.SelectedRemoteBuild is not BuildFile buildFile)
|
||||
if (this.SelectedRemoteBuild is not SynchronizationBuild build)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ButtonsEnabled = false;
|
||||
this.ShowLoading = true;
|
||||
await this.graphClient.DownloadBuild(buildFile.FileName);
|
||||
await this.graphClient.DownloadBuild(build.Name);
|
||||
await this.PopulateBuilds();
|
||||
this.ButtonsEnabled = true;
|
||||
this.ShowLoading = false;
|
||||
@@ -166,4 +184,25 @@ public partial class BuildsSynchronizationView : UserControl
|
||||
this.ButtonsEnabled = true;
|
||||
this.ShowLoading = false;
|
||||
}
|
||||
|
||||
private async void LogOutButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.ButtonsEnabled = false;
|
||||
this.ShowLoading = true;
|
||||
var result = await this.graphClient.LogOut();
|
||||
result.Do(
|
||||
onSuccess: logOutSuccess =>
|
||||
{
|
||||
if (logOutSuccess)
|
||||
{
|
||||
this.viewManager.ShowView<BuildsListView>();
|
||||
}
|
||||
},
|
||||
onFailure: failure =>
|
||||
{
|
||||
this.logger.LogError(failure, "Failed to log out");
|
||||
});
|
||||
this.ButtonsEnabled = true;
|
||||
this.ShowLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Screens;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Extensions;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Extensions;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Daybreak.Services.Graph;
|
||||
using Daybreak.Services.Graph.Models;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Models.Progress;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
using System.Windows.Controls;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using Daybreak.Controls.Templates;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Screens;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Extensions;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Extensions;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Models.Progress;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Updater;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
|
||||
Reference in New Issue
Block a user