mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-16 13:29:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
624380ed86 | ||
|
|
2b025e225b | ||
|
|
15a67ea28c | ||
|
|
c6b62fd5fd | ||
|
|
3c0877c1a0 | ||
|
|
967b57b9a8 | ||
|
|
f47cc319b5 | ||
|
|
26da84c4e7 | ||
|
|
a39e8dc5c6 | ||
|
|
1bb4669135 | ||
|
|
0203eef006 | ||
|
|
4ab50ee191 | ||
|
|
06c1ec1ac2 | ||
|
|
ef4befdc38 | ||
|
|
33f49ddffa | ||
|
|
49aa249b5b |
+24
-38
@@ -5,12 +5,11 @@
|
||||
# This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
|
||||
name: Daybreak CD Pipeline
|
||||
|
||||
# Trigger on every master branch push and pull request
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
@@ -26,76 +25,63 @@ jobs:
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreal.csproj
|
||||
Actions_Allow_Unsecure_Commands: true # Allows AddPAth and SetEnv commands
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Latest Tag
|
||||
id: getLatestTag
|
||||
uses: WyriHaximus/github-action-get-previous-tag@v1
|
||||
|
||||
- name: Generate changelog
|
||||
id: gen_changelog
|
||||
run: |
|
||||
$changeLog = git log --no-merges --pretty="%h - %s (%an)<br />" ${{ env.LatestReleaseTag }}..HEAD
|
||||
echo "::set-env name=Changelog::$changeLog"
|
||||
env:
|
||||
LatestReleaseTag: ${{steps.getLatestTag.outputs.tag}}
|
||||
|
||||
- name: Print changelog
|
||||
run: |
|
||||
echo "${{ env.Changelog }}"
|
||||
|
||||
# Install the .NET Core workload
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.202'
|
||||
|
||||
# Add MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.1
|
||||
|
||||
# Restore the application
|
||||
- name: Restore the Wpf application to populate the obj folder
|
||||
- name: Restore project
|
||||
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
# Build Daybreak project
|
||||
- name: Build Daybreak project
|
||||
run: dotnet build Daybreak -c $env:Configuration
|
||||
|
||||
# Set release version environment variable
|
||||
- name: Set version variable
|
||||
run: |
|
||||
$version = .\Scripts\GetBuildVersion.ps1
|
||||
echo "::set-env name=Version::$version"
|
||||
|
||||
# Publish release
|
||||
- name: Publish release
|
||||
- name: Create publish files
|
||||
run: dotnet publish .\Daybreak\Daybreak.csproj -c $env:Configuration -r $env:RuntimeIdentifier -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -o .\Publish
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
# Create release payload
|
||||
- name: Create release payload
|
||||
- name: Pack publish files
|
||||
run: |
|
||||
Write-Host $env
|
||||
.\Scripts\BuildRelease.ps1 -version $env:Version
|
||||
shell: pwsh
|
||||
|
||||
# Get latest release
|
||||
- name: Get latest release tag
|
||||
id: download_release
|
||||
uses: Xotl/cool-github-releases@v1.1.2
|
||||
with:
|
||||
mode: download
|
||||
github_token: ${{ env.GITHUB_TOKEN }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Generate changelog
|
||||
- name: Generate changelog
|
||||
id: gen_changelog
|
||||
uses: mikepenz/release-changelog-builder-action@v1.8.0
|
||||
with:
|
||||
fromTag: ${{ steps.download_release.outputs.tag_name }}
|
||||
toTag: ${{ env.Version }}
|
||||
token: ${{ env.GITHUB_TOKEN }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Post new release to github
|
||||
- name: Post release
|
||||
- name: Publish release
|
||||
uses: Xotl/cool-github-releases@v1.1.2
|
||||
with:
|
||||
mode: update
|
||||
@@ -104,7 +90,7 @@ jobs:
|
||||
assets: .\Publish\daybreakv${{ env.Version }}.zip
|
||||
github_token: ${{ env.GITHUB_TOKEN }}
|
||||
replace_assets: true
|
||||
body_mrkdwn: ${{ steps.gen_changelog.outputs.changelog }}
|
||||
body_mrkdwn: ${{ env.Changelog }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
|
||||
name: Daybreak CI Pipeline
|
||||
|
||||
# Trigger on every master branch push and pull request
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -28,29 +27,25 @@ jobs:
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreal.csproj
|
||||
Actions_Allow_Unsecure_Commands: true # Allows AddPAth and SetEnv commands
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
|
||||
fetch-depth: 0
|
||||
|
||||
# Install the .NET Core workload
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.202'
|
||||
|
||||
# Add MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.1
|
||||
|
||||
# Test
|
||||
- name: Execute Unit Tests
|
||||
run: dotnet test $env:Test_Project_Path
|
||||
|
||||
# Restore the application
|
||||
- name: Restore the Wpf application to populate the obj folder
|
||||
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
|
||||
env:
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
<PackageReference Include="System.Linq.Async" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
using Daybreak.Models.Versioning;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Version = Daybreak.Models.Versioning.Version;
|
||||
|
||||
namespace Daybreak.Tests.Models
|
||||
{
|
||||
[TestClass]
|
||||
public class VersionTests
|
||||
{
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0.1")]
|
||||
[DataRow("v0.1.0.0.1.0.0.0.0", "v0.1.0.0.1")]
|
||||
[DataRow("v0.1.0", "v0.1")]
|
||||
[DataRow("0.1.0", "0.1")]
|
||||
[DataRow("v0.1.0.0.0", "v0.1")]
|
||||
[DataRow("0.1.0.0.0", "0.1")]
|
||||
[DataRow("v0", "v0")]
|
||||
[DataRow("0", "0")]
|
||||
[DataRow("v0.1", "v0.1")]
|
||||
[DataRow("0.1-release", "0.1-release")]
|
||||
[DataRow("v0.1-release", "v0.1-release")]
|
||||
[TestMethod]
|
||||
public void VersionToString(string version, string expectedString)
|
||||
{
|
||||
var parsedVersion = Version.Parse(version);
|
||||
parsedVersion.ToString().Should().Be(expectedString);
|
||||
}
|
||||
|
||||
[DataRow("v0", false)]
|
||||
[DataRow("0", false)]
|
||||
[DataRow("v0.1", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("v0.1-release", true)]
|
||||
[TestMethod]
|
||||
public void VersionHasStringSuffix(string version, bool hasSuffix)
|
||||
{
|
||||
var parsedVersion = Version.Parse(version);
|
||||
if (hasSuffix)
|
||||
{
|
||||
parsedVersion.VersionTokens.Last().Should().BeOfType<VersionStringToken>();
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedVersion.VersionTokens.Last().Should().BeOfType<VersionNumberToken>();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow("v0", true)]
|
||||
[DataRow("0", false)]
|
||||
[DataRow("v0.1", true)]
|
||||
[DataRow("0.1", false)]
|
||||
[TestMethod]
|
||||
public void VersionTokensHasPrefix(string version, bool hasPrefix)
|
||||
{
|
||||
var parsedVersion = Version.Parse(version);
|
||||
parsedVersion.HasPrefix.Should().Be(hasPrefix);
|
||||
}
|
||||
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("asd", false)]
|
||||
[DataRow("ads.pls.er", false)]
|
||||
[DataRow("0.0.1", true)]
|
||||
[DataRow("1", true)]
|
||||
[DataRow("0.1.asd", false)]
|
||||
[DataRow("0.", false)]
|
||||
[DataRow(".1", false)]
|
||||
[DataRow("0.1-", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("0..1", false)]
|
||||
[TestMethod]
|
||||
public void TryParseVersionTest(string version, bool result)
|
||||
{
|
||||
var success = Version.TryParse(version, out var parsedVersion);
|
||||
success.Should().Be(result);
|
||||
if (success is true)
|
||||
{
|
||||
parsedVersion.Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("asd", false)]
|
||||
[DataRow("ads.pls.er", false)]
|
||||
[DataRow("0.0.1", true)]
|
||||
[DataRow("1", true)]
|
||||
[DataRow("0.1.asd", false)]
|
||||
[DataRow("0.", false)]
|
||||
[DataRow(".1", false)]
|
||||
[DataRow("0.1-", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("0..1", false)]
|
||||
[TestMethod]
|
||||
public void ParseVersionTest(string version, bool shouldNotThrow)
|
||||
{
|
||||
var action = new Action(() => Version.Parse(version));
|
||||
if (shouldNotThrow is false)
|
||||
{
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.Should().NotThrow<InvalidOperationException>();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow(null, false)]
|
||||
[DataRow("", false)]
|
||||
[DataRow("asd", false)]
|
||||
[DataRow("ads.pls.er", false)]
|
||||
[DataRow("0.0.1", true)]
|
||||
[DataRow("1", true)]
|
||||
[DataRow("0.1.asd", false)]
|
||||
[DataRow("0.", false)]
|
||||
[DataRow(".1", false)]
|
||||
[DataRow("0.1-", false)]
|
||||
[DataRow("0.1-release", true)]
|
||||
[DataRow("0..1", false)]
|
||||
[TestMethod]
|
||||
public void VersionConstructorTest(string version, bool shouldNotThrow)
|
||||
{
|
||||
var action = new Action(() => new Version(version));
|
||||
if (shouldNotThrow is false)
|
||||
{
|
||||
action.Should().Throw<ArgumentException>();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.Should().NotThrow<ArgumentException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Options;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Tests.Services
|
||||
{
|
||||
[TestClass]
|
||||
public class ApplicationConfigurationOptionsManagerTests
|
||||
{
|
||||
private ApplicationConfigurationOptionsManager applicationConfigurationOptionsManager;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
var configurationManagerMock = new Mock<IConfigurationManager>();
|
||||
configurationManagerMock
|
||||
.Setup(u => u.GetConfiguration())
|
||||
.Returns(new ApplicationConfiguration());
|
||||
|
||||
this.applicationConfigurationOptionsManager = new ApplicationConfigurationOptionsManager(configurationManagerMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetApplicationConfiguration_ReturnsObject()
|
||||
{
|
||||
var config = this.applicationConfigurationOptionsManager.GetOptions<ApplicationConfiguration>();
|
||||
|
||||
config.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetOtherOptions_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = new Action(() =>
|
||||
{
|
||||
this.applicationConfigurationOptionsManager.GetOptions<object>();
|
||||
});
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateOptions_OnApplicationConfiguration_Succeeds()
|
||||
{
|
||||
this.applicationConfigurationOptionsManager.UpdateOptions(new ApplicationConfiguration());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateOptions_OnOthers_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = new Action(() =>
|
||||
{
|
||||
this.applicationConfigurationOptionsManager.UpdateOptions(new object());
|
||||
});
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Logging;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System.Collections.Generic;
|
||||
@@ -17,7 +17,7 @@ namespace Daybreak.Tests.Services
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
buildTemplateManager = new BuildTemplateManager(new Mock<ILogger>().Object);
|
||||
buildTemplateManager = new BuildTemplateManager(new Mock<ILogger<BuildTemplateManager>>().Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
using Daybreak.Services.Logging;
|
||||
using FluentAssertions;
|
||||
using LiteDB;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using WpfExtended.Logging;
|
||||
|
||||
namespace Daybreak.Tests.Services
|
||||
{
|
||||
[TestClass]
|
||||
public class JsonLoggerProviderTests
|
||||
{
|
||||
private ILogsManager logsManager;
|
||||
private ILoggerProvider loggerProvider;
|
||||
private ILiteDatabase liteDatabase;
|
||||
|
||||
[TestInitialize]
|
||||
public void InitializeProvider()
|
||||
{
|
||||
File.Delete("Daybreak.db");
|
||||
this.liteDatabase = new LiteDatabase("Daybreak.db");
|
||||
this.logsManager = new JsonLogsManager(this.liteDatabase);
|
||||
this.loggerProvider = new CVLoggerProvider(this.logsManager);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
this.liteDatabase.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateLoggerReturnsLogger()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.Should().NotBeNull();
|
||||
}
|
||||
[TestMethod]
|
||||
public void LoggerLogsAndReaderReadsFiltered()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.LogTrace("Logging some trace");
|
||||
logger.LogInformation("Logging some stuff");
|
||||
logger.LogError("Logging some error");
|
||||
|
||||
this.logsManager.GetLogs(l => l.LogLevel < LogLevel.Information).Should().HaveCount(1);
|
||||
var log = this.logsManager.GetLogs(l => l.LogLevel < LogLevel.Information).First();
|
||||
log.LogLevel.Should().Be(LogLevel.Error);
|
||||
}
|
||||
[TestMethod]
|
||||
public void LoggerLogsAndReaderReads()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.LogInformation("Logging some stuff");
|
||||
logger.LogError("Logging some error");
|
||||
|
||||
this.logsManager.GetLogs().Should().HaveCount(2);
|
||||
}
|
||||
[TestMethod]
|
||||
public void DeletingLogsShouldDeleteLogs()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.LogInformation("Logging some stuff");
|
||||
logger.LogError("Logging some error");
|
||||
|
||||
this.logsManager.GetLogs().Should().HaveCount(2);
|
||||
|
||||
this.logsManager.DeleteLogs();
|
||||
this.logsManager.GetLogs().Should().HaveCount(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.31005.135
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak", "Daybreak\Daybreak.csproj", "{AA45C2B1-8BD0-466C-9271-699F168905AF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daybreak.Tests", "Daybreak.Tests\Daybreak.Tests.csproj", "{C911C1C2-6566-419C-89C7-F802EB3FE709}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak.Tests", "Daybreak.Tests\Daybreak.Tests.csproj", "{C911C1C2-6566-419C-89C7-F802EB3FE709}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -17,12 +17,12 @@ Global
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.Build.0 = Debug|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.ActiveCfg = Release|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.Build.0 = Release|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
||||
@@ -35,5 +35,9 @@ namespace Daybreak.Configuration
|
||||
public string ShortcutLocation { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
[JsonProperty("PlaceShortcut")]
|
||||
public bool PlaceShortcut { get; set; }
|
||||
[JsonProperty("AutoCheckUpdate")]
|
||||
public bool AutoCheckUpdate { get; set; } = true;
|
||||
[JsonProperty("KeepLocalIconCache")]
|
||||
public bool KeepLocalIconCache { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
@@ -8,51 +7,63 @@ using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.Mutex;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Runtime;
|
||||
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;
|
||||
using Slim;
|
||||
using System.Extensions;
|
||||
using System.Net.Http;
|
||||
using System.Windows.Extensions.Http;
|
||||
using LiteDB;
|
||||
using System.Windows.Extensions;
|
||||
using Daybreak.Services.Options;
|
||||
|
||||
namespace Daybreak.Configuration
|
||||
{
|
||||
public static class ProjectConfiguration
|
||||
{
|
||||
public static void RegisterResolvers(IServiceManager serviceManager)
|
||||
{
|
||||
serviceManager.ThrowIfNull(nameof(serviceManager));
|
||||
|
||||
serviceManager.RegisterResolver(
|
||||
new HttpClientResolver()
|
||||
.WithHttpMessageHandlerFactory((serviceProvider, categoryType) =>
|
||||
{
|
||||
var loggerType = typeof(ILogger<>).MakeGenericType(categoryType);
|
||||
var logger = serviceProvider.GetService(loggerType).As<ILogger>();
|
||||
var handler = new LoggingHttpMessageHandler(logger) { InnerHandler = new HttpClientHandler() };
|
||||
return handler;
|
||||
}));
|
||||
serviceManager.RegisterOptionsManager<ApplicationConfigurationOptionsManager>();
|
||||
}
|
||||
|
||||
public static void RegisterServices(IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceProducer.RegisterSingleton<ICredentialManager, CredentialManager>();
|
||||
serviceProducer.RegisterSingleton<ILoggingDatabase, FlatLoggingDatabase>();
|
||||
serviceProducer.RegisterSingleton<ILogger, Logger>();
|
||||
serviceProducer.RegisterSingleton<ApplicationLifetimeManager>();
|
||||
serviceProducer.RegisterSingleton<ViewManager>();
|
||||
serviceProducer.RegisterSingleton<IApplicationLauncher, ApplicationLauncher>();
|
||||
serviceProducer.RegisterSingleton<IScreenshotProvider, ScreenshotProvider>();
|
||||
serviceProducer.RegisterSingleton<IConfigurationManager, ConfigurationManager>();
|
||||
serviceProducer.RegisterSingleton<IBloogumClient, BloogumClient>();
|
||||
serviceProducer.RegisterSingleton<IApplicationUpdater, ApplicationUpdater>();
|
||||
serviceProducer.RegisterSingleton<ILiteDatabase, LiteDatabase>(sp => new LiteDatabase("Daybreak.db"));
|
||||
serviceProducer.RegisterSingleton<IMutexHandler, MutexHandler>();
|
||||
serviceProducer.RegisterSingleton<IRuntimeStore, RuntimeStore>();
|
||||
serviceProducer.RegisterSingleton<IBuildTemplateManager, BuildTemplateManager>();
|
||||
serviceProducer.RegisterSingleton<IIconRetriever, IconRetriever>();
|
||||
serviceProducer.RegisterSingleton<IPrivilegeManager, PrivilegeManager>();
|
||||
serviceProducer.RegisterSingleton<IScreenManager, ScreenManager>();
|
||||
serviceProducer.RegisterSingleton<IShortcutManager, ShortcutManager>();
|
||||
serviceProducer.RegisterScoped<ICredentialManager, CredentialManager>();
|
||||
serviceProducer.RegisterScoped<IApplicationLauncher, ApplicationLauncher>();
|
||||
serviceProducer.RegisterScoped<IScreenshotProvider, ScreenshotProvider>();
|
||||
serviceProducer.RegisterScoped<IBloogumClient, BloogumClient>();
|
||||
serviceProducer.RegisterScoped<IApplicationUpdater, ApplicationUpdater>();
|
||||
serviceProducer.RegisterScoped<IBuildTemplateManager, BuildTemplateManager>();
|
||||
serviceProducer.RegisterScoped<IIconRetriever, IconRetriever>();
|
||||
serviceProducer.RegisterScoped<IPrivilegeManager, PrivilegeManager>();
|
||||
serviceProducer.RegisterScoped<IScreenManager, ScreenManager>();
|
||||
serviceProducer.RegisterLogWriter<ILogsManager, JsonLogsManager>();
|
||||
}
|
||||
public static void RegisterLifetimeServices(IApplicationLifetimeProducer applicationLifetimeProducer)
|
||||
{
|
||||
applicationLifetimeProducer.ThrowIfNull(nameof(applicationLifetimeProducer));
|
||||
|
||||
applicationLifetimeProducer.RegisterService<ILoggingDatabase>();
|
||||
applicationLifetimeProducer.RegisterService<IScreenshotProvider>();
|
||||
applicationLifetimeProducer.RegisterService<IApplicationUpdater>();
|
||||
applicationLifetimeProducer.RegisterService<IShortcutManager>();
|
||||
}
|
||||
public static void RegisterViews(IViewProducer viewProducer)
|
||||
{
|
||||
viewProducer.ThrowIfNull(nameof(viewProducer));
|
||||
@@ -69,6 +80,8 @@ namespace Daybreak.Configuration
|
||||
viewProducer.RegisterView<BuildsListView>();
|
||||
viewProducer.RegisterView<RequestElevationView>();
|
||||
viewProducer.RegisterView<ScreenChoiceView>();
|
||||
viewProducer.RegisterView<VersionManagementView>();
|
||||
viewProducer.RegisterView<LogsView>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Models.Browser;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@@ -23,15 +23,18 @@ namespace Daybreak.Controls
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Used by source generators")]
|
||||
public partial class ChromiumBrowserWrapper : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty AddressProperty =
|
||||
DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, string>(nameof(Address));
|
||||
|
||||
private const string BrowserDownloadLink = "https://developer.microsoft.com/en-us/microsoft-edge/webview2/";
|
||||
|
||||
public event EventHandler<string> FavoriteUriChanged;
|
||||
public event EventHandler MaximizeClicked;
|
||||
public event EventHandler<Build> BuildDecoded;
|
||||
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILogger logger;
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
private ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
private ILogger<ChromiumBrowserWrapper> logger;
|
||||
private IBuildTemplateManager buildTemplateManager;
|
||||
private CoreWebView2Environment coreWebView2Environment;
|
||||
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
@@ -40,7 +43,7 @@ namespace Daybreak.Controls
|
||||
private bool canNavigate;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool controlsEnabled;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
[GenerateDependencyProperty]
|
||||
private bool browserSupported;
|
||||
[GenerateDependencyProperty]
|
||||
private bool addressBarReadonly;
|
||||
@@ -50,17 +53,22 @@ namespace Daybreak.Controls
|
||||
private bool navigating;
|
||||
[GenerateDependencyProperty]
|
||||
private string favoriteAddress;
|
||||
[GenerateDependencyProperty]
|
||||
private string address;
|
||||
public string Address
|
||||
{
|
||||
get => this.GetTypedValue<string>(AddressProperty);
|
||||
set
|
||||
{
|
||||
if (this.BrowserSupported is true)
|
||||
{
|
||||
this.SetValue(AddressProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChromiumBrowserWrapper()
|
||||
{
|
||||
this.configurationManager = Launcher.ApplicationServiceManager.GetService<IConfigurationManager>();
|
||||
this.logger = Launcher.ApplicationServiceManager.GetService<ILogger>();
|
||||
this.buildTemplateManager = Launcher.ApplicationServiceManager.GetService<IBuildTemplateManager>();
|
||||
this.InitializeComponent();
|
||||
this.InitializeEnvironment();
|
||||
this.InitializeBrowser();
|
||||
this.WebBrowser.IsEnabled = false;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
@@ -72,6 +80,18 @@ namespace Daybreak.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public async void InitializeBrowser(
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> logger)
|
||||
{
|
||||
this.liveOptions = liveOptions;
|
||||
this.buildTemplateManager = buildTemplateManager;
|
||||
this.logger = logger;
|
||||
this.InitializeEnvironment();
|
||||
await this.InitializeBrowser();
|
||||
}
|
||||
|
||||
public async void ReinitializeBrowser()
|
||||
{
|
||||
await this.InitializeBrowser();
|
||||
@@ -79,7 +99,7 @@ namespace Daybreak.Controls
|
||||
|
||||
private void InitializeEnvironment()
|
||||
{
|
||||
if (this.configurationManager.GetConfiguration().BrowsersEnabled is false)
|
||||
if (this.liveOptions.Value.BrowsersEnabled is false)
|
||||
{
|
||||
this.BrowserSupported = false;
|
||||
return;
|
||||
@@ -101,9 +121,10 @@ namespace Daybreak.Controls
|
||||
{
|
||||
if (this.BrowserSupported is true)
|
||||
{
|
||||
this.WebBrowser.IsEnabled = true;
|
||||
await this.WebBrowser.EnsureCoreWebView2Async(this.coreWebView2Environment);
|
||||
this.AddressBarReadonly = this.configurationManager.GetConfiguration().AddressBarReadonly;
|
||||
this.CanDownloadBuild = this.configurationManager.GetConfiguration().ExperimentalFeatures.DynamicBuildLoading;
|
||||
this.AddressBarReadonly = this.liveOptions.Value.AddressBarReadonly;
|
||||
this.CanDownloadBuild = this.liveOptions.Value.ExperimentalFeatures.DynamicBuildLoading;
|
||||
this.WebBrowser.CoreWebView2.NewWindowRequested += (browser, args) => args.Handled = true;
|
||||
this.WebBrowser.NavigationStarting += (browser, args) =>
|
||||
{
|
||||
@@ -174,7 +195,7 @@ namespace Daybreak.Controls
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
this.logger.LogError(e);
|
||||
this.logger.LogError(e, $"Exception encountered when deserializing {nameof(BrowserPayload)}");
|
||||
}
|
||||
if (payload?.Key == BrowserPayload.PayloadKeys.ContextMenu)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl x:Class="Daybreak.Controls.LogsGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m7,3l0,-1.00209c0,-1.09965 0.89762,-1.99791 2.00488,-1.99791l0.99024,0c1.11098,0 2.00488,0.8945 2.00488,1.99791l0,1.00209l2.00442,0c0.55074,0 0.99558,0.44725 0.99558,0.99896l0,1.00208c0,0.5563 -0.44574,0.99896 -0.99558,0.99896l-9.00884,0c-0.55074,0 -0.99558,-0.44725 -0.99558,-0.99896l0,-1.00208c0,-0.5563 0.44574,-0.99896 0.99558,-0.99896l2.00442,0l0,0zm8.99999,1l1.00259,0c1.10649,0 1.99742,0.89704 1.99742,2.00359l0,20.99282c0,1.11383 -0.89428,2.00359 -1.99742,2.00359l-15.00516,0c-1.10649,0 -1.99742,-0.89704 -1.99742,-2.00359l0,-20.99282c0,-1.11383 0.89428,-2.00359 1.99742,-2.00359l1.00259,0c-0.00001,0.00163 -0.00001,0.00325 -0.00001,0.00488l0,0.99024c0,1.10726 0.89354,2.00488 2.00276,2.00488l8.99448,0c1.10609,0 2.00276,-0.8939 2.00276,-2.00488l0,-0.99024c0,-0.00163 0,-0.00325 -0.00001,-0.00488l0,0l0,0zm-6.49999,-1c0.27614,0 0.5,-0.22386 0.5,-0.5c0,-0.27614 -0.22386,-0.5 -0.5,-0.5c-0.27614,0 -0.5,0.22386 -0.5,0.5c0,0.27614 0.22386,0.5 0.5,0.5l0,0zm-6.5,8l0,1l13,0l0,-1l-13,0l0,0zm0,3l0,1l13,0l0,-1l-13,0l0,0zm0,3l0,1l13,0l0,-1l-13,0l0,0zm0,3l0,1l13,0l0,-1l-13,0l0,0zm0,3l0,1l13,0l0,-1l-13,0l0,0z"></Path>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for LogsGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class LogsGlyph : UserControl
|
||||
{
|
||||
public LogsGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl x:Class="Daybreak.Controls.StaticGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Polygon Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Points="209.89999389648438,829.800048828125 279.1999816894531,493.9000244140625 0,493.9000244140625 415.89996337890625,0 346.699951171875,335.8999938964844 625.800048828125,335.8999938964844"></Polygon>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for StaticGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class StaticGlyph : UserControl
|
||||
{
|
||||
public StaticGlyph()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ namespace Daybreak.Controls
|
||||
public partial class AttributeTemplate : UserControl
|
||||
{
|
||||
public event EventHandler<AttributeEntry> HelpClicked;
|
||||
public event EventHandler<AttributeEntry> AttributeChanged;
|
||||
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool canAdd;
|
||||
@@ -50,6 +51,7 @@ namespace Daybreak.Controls
|
||||
this.DataContext.As<AttributeEntry>().Points--;
|
||||
this.CanSubtract = this.DataContext.As<AttributeEntry>().Points > 0;
|
||||
this.CanAdd = true;
|
||||
this.AttributeChanged?.Invoke(this, this.DataContext.As<AttributeEntry>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +62,7 @@ namespace Daybreak.Controls
|
||||
this.DataContext.As<AttributeEntry>().Points++;
|
||||
this.CanAdd = this.DataContext.As<AttributeEntry>().Points < 12;
|
||||
this.CanSubtract = true;
|
||||
this.AttributeChanged?.Invoke(this, this.DataContext.As<AttributeEntry>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
HorizontalContentAlignment="Stretch" BorderThickness="0">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:AttributeTemplate HelpClicked="AttributeTemplate_HelpClicked"></local:AttributeTemplate>
|
||||
<local:AttributeTemplate HelpClicked="AttributeTemplate_HelpClicked" AttributeChanged="AttributeTemplate_AttributeChanged"></local:AttributeTemplate>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
@@ -95,42 +95,42 @@
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<local:SkillTemplate Grid.Column="0"
|
||||
<local:SkillTemplate Grid.Column="0" x:Name="SkillTemplate0"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill0, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="1"
|
||||
<local:SkillTemplate Grid.Column="1" x:Name="SkillTemplate1"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill1, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="2"
|
||||
<local:SkillTemplate Grid.Column="2" x:Name="SkillTemplate2"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill2, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="3"
|
||||
<local:SkillTemplate Grid.Column="3" x:Name="SkillTemplate3"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill3, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="4"
|
||||
<local:SkillTemplate Grid.Column="4" x:Name="SkillTemplate4"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill4, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="5"
|
||||
<local:SkillTemplate Grid.Column="5" x:Name="SkillTemplate5"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill5, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="6"
|
||||
<local:SkillTemplate Grid.Column="6" x:Name="SkillTemplate6"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill6, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="7"
|
||||
<local:SkillTemplate Grid.Column="7" x:Name="SkillTemplate7"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill7, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Extensions;
|
||||
@@ -19,10 +25,13 @@ namespace Daybreak.Controls
|
||||
private const string InfoNamePlaceholder = "[NAME]";
|
||||
private const string BaseAddress = $"https://wiki.guildwars.com/wiki/{InfoNamePlaceholder}";
|
||||
|
||||
private bool suppressBuildChanged = false;
|
||||
private bool loadedProperties = false;
|
||||
private BuildEntry loadedBuild;
|
||||
private SkillTemplate selectingSkillTemplate;
|
||||
|
||||
public event EventHandler BuildChanged;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private Profession primaryProfession;
|
||||
[GenerateDependencyProperty]
|
||||
@@ -54,6 +63,23 @@ namespace Daybreak.Controls
|
||||
this.DataContextChanged += BuildTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
public void InitializeTemplate(
|
||||
IIconRetriever iconRetriever,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> logger)
|
||||
{
|
||||
this.SkillBrowser.InitializeBrowser(liveOptions, buildTemplateManager, logger);
|
||||
this.SkillTemplate0.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate1.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate2.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate3.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate4.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate5.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate6.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate7.InitializeSkillTemplate(iconRetriever);
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
@@ -74,6 +100,33 @@ namespace Daybreak.Controls
|
||||
}
|
||||
this.LoadSkills();
|
||||
this.LoadAttributes();
|
||||
if (this.suppressBuildChanged is false)
|
||||
{
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Property == Skill0Property ||
|
||||
e.Property == Skill1Property ||
|
||||
e.Property == Skill2Property ||
|
||||
e.Property == Skill3Property ||
|
||||
e.Property == Skill4Property ||
|
||||
e.Property == Skill5Property ||
|
||||
e.Property == Skill6Property ||
|
||||
e.Property == Skill7Property)
|
||||
{
|
||||
if (this.suppressBuildChanged is false)
|
||||
{
|
||||
this.loadedBuild.Build.Skills[0] = this.Skill0;
|
||||
this.loadedBuild.Build.Skills[1] = this.Skill1;
|
||||
this.loadedBuild.Build.Skills[2] = this.Skill2;
|
||||
this.loadedBuild.Build.Skills[3] = this.Skill3;
|
||||
this.loadedBuild.Build.Skills[4] = this.Skill4;
|
||||
this.loadedBuild.Build.Skills[5] = this.Skill5;
|
||||
this.loadedBuild.Build.Skills[6] = this.Skill6;
|
||||
this.loadedBuild.Build.Skills[7] = this.Skill7;
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +250,7 @@ namespace Daybreak.Controls
|
||||
|
||||
private void LoadBuild()
|
||||
{
|
||||
this.suppressBuildChanged = true;
|
||||
var build = this.DataContext.As<BuildEntry>();
|
||||
this.loadedBuild = build;
|
||||
this.PrimaryProfession = build.Build.Primary;
|
||||
@@ -209,6 +263,7 @@ namespace Daybreak.Controls
|
||||
this.Skill5 = build.Build.Skills[5];
|
||||
this.Skill6 = build.Build.Skills[6];
|
||||
this.Skill7 = build.Build.Skills[7];
|
||||
this.suppressBuildChanged = false;
|
||||
}
|
||||
|
||||
private void BrowseToInfo(string infoName)
|
||||
@@ -220,13 +275,19 @@ namespace Daybreak.Controls
|
||||
|
||||
private void ShowInfoBrowser()
|
||||
{
|
||||
this.SkillBrowser.Width = 400;
|
||||
this.SkillsListView.Width = 0;
|
||||
if (this.SkillBrowser.BrowserSupported is true)
|
||||
{
|
||||
this.SkillBrowser.Width = 400;
|
||||
this.SkillsListView.Width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void HideInfoBrowser()
|
||||
{
|
||||
this.SkillBrowser.Width = 0;
|
||||
if (this.SkillBrowser.BrowserSupported is true)
|
||||
{
|
||||
this.SkillBrowser.Width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowSkillListView()
|
||||
@@ -273,6 +334,11 @@ namespace Daybreak.Controls
|
||||
this.BrowseToInfo(e.Attribute.Name);
|
||||
}
|
||||
|
||||
private void AttributeTemplate_AttributeChanged(object sender, AttributeEntry e)
|
||||
{
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
|
||||
private void SkillTemplate_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var skill = sender.As<SkillTemplate>().DataContext.As<Skill>();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<UserControl x:Class="Daybreak.Controls.LogMessageTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Message, Mode=OneWay}" Background="Transparent"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
MouseLeftButtonDown="TextBox_MouseLeftButtonDown" MaxHeight="18" TextWrapping="Wrap"></TextBlock>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Extensions;
|
||||
|
||||
namespace Daybreak.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for LogTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class LogMessageTemplate : UserControl
|
||||
{
|
||||
private bool expanded;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string message;
|
||||
|
||||
public LogMessageTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void TextBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs eventArgs)
|
||||
{
|
||||
this.expanded = !this.expanded;
|
||||
if (this.expanded)
|
||||
{
|
||||
sender.As<TextBlock>().MaxHeight = double.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.As<TextBlock>().MaxHeight = 18;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace Daybreak.Controls
|
||||
public event EventHandler<RoutedEventArgs> Clicked;
|
||||
public event EventHandler RemoveClicked;
|
||||
|
||||
private readonly IIconRetriever iconRetriever;
|
||||
private IIconRetriever iconRetriever;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ImageSource imageSource;
|
||||
@@ -32,22 +32,26 @@ namespace Daybreak.Controls
|
||||
|
||||
public SkillTemplate()
|
||||
{
|
||||
this.iconRetriever = Launcher.ApplicationServiceManager.GetService<IIconRetriever>();
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += SkillTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
public void InitializeSkillTemplate(IIconRetriever iconRetriever)
|
||||
{
|
||||
this.iconRetriever = iconRetriever;
|
||||
}
|
||||
|
||||
private void SkillTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.NewValue is Skill skill)
|
||||
{
|
||||
if (skill != Skill.NoSkill)
|
||||
{
|
||||
Task.Run(() => GetImageStream(skill)).ContinueWith((previousTask) =>
|
||||
Task.Run(() => this.GetImageStream(skill)).ContinueWith((previousTask) =>
|
||||
{
|
||||
this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.ImageSource = GetImageSource(previousTask.Result);
|
||||
this.ImageSource = this.GetImageSource(previousTask.Result);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -88,6 +92,11 @@ namespace Daybreak.Controls
|
||||
}
|
||||
private async Task<Stream> GetImageStream(Skill skill)
|
||||
{
|
||||
if (this.iconRetriever is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var maybeStream = await this.iconRetriever.GetIcon(skill);
|
||||
return maybeStream.ExtractValue();
|
||||
}
|
||||
|
||||
@@ -10,19 +10,24 @@
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
|
||||
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
|
||||
<Version>0.8.8</Version>
|
||||
<Version>0.9.2.4</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.32" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.818.41" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.10" />
|
||||
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.864.35" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="NReco.Logging.File" Version="1.1.1" />
|
||||
<PackageReference Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageReference Include="Slim" Version="1.2.2" />
|
||||
<PackageReference Include="Slim" Version="1.5.1" />
|
||||
<PackageReference Include="System.Windows.Interactivity.WPF" Version="2.0.20525" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.1.4" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.3.0" />
|
||||
<PackageReference Include="WCL" Version="1.0.2" />
|
||||
<PackageReference Include="WpfExtended" Version="0.2.1" />
|
||||
<PackageReference Include="WpfExtended" Version="0.5.2" />
|
||||
<PackageReference Include="WpfExtended.SourceGeneration" Version="0.1.1" />
|
||||
<PackageReference Include="WpfScreenHelper" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
@@ -65,7 +70,7 @@
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
||||
<Exec Command="echo.>$(Version).version" />
|
||||
</Target>
|
||||
|
||||
|
||||
+30
-13
@@ -1,17 +1,13 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Web.WebView2.Wpf;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Slim;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
@@ -19,7 +15,7 @@ namespace Daybreak.Launch
|
||||
{
|
||||
public sealed class Launcher : ExtendedApplication<MainWindow>
|
||||
{
|
||||
public static IServiceManager ApplicationServiceManager { get; private set; }
|
||||
private ILogger logger;
|
||||
private readonly static Launcher launcher = new();
|
||||
|
||||
[STAThread]
|
||||
@@ -28,10 +24,14 @@ namespace Daybreak.Launch
|
||||
return LaunchMainWindow();
|
||||
}
|
||||
|
||||
protected override void SetupServiceManager(IServiceManager serviceManager)
|
||||
{
|
||||
ProjectConfiguration.RegisterResolvers(serviceManager);
|
||||
}
|
||||
protected override void RegisterServices(IServiceProducer serviceProducer)
|
||||
{
|
||||
ProjectConfiguration.RegisterServices(this.ServiceManager);
|
||||
ProjectConfiguration.RegisterLifetimeServices(this.ServiceManager.GetService<IApplicationLifetimeManager>());
|
||||
ServiceManager.BuildSingletons();
|
||||
ProjectConfiguration.RegisterViews(this.ServiceManager.GetService<IViewManager>());
|
||||
}
|
||||
protected override bool HandleException(Exception e)
|
||||
@@ -41,10 +41,18 @@ namespace Daybreak.Launch
|
||||
return false;
|
||||
}
|
||||
|
||||
this.ServiceManager.GetService<ILogger>().LogCritical(e);
|
||||
if (e is FatalException fatalException)
|
||||
{
|
||||
this.logger.LogCritical(e, $"{nameof(FatalException)} encountered. Closing application");
|
||||
MessageBox.Show(fatalException.ToString());
|
||||
File.WriteAllText("crash.log", e.ToString());
|
||||
return false;
|
||||
}
|
||||
else if (e is TargetInvocationException targetInvocationException && e.InnerException is FatalException innerFatalException)
|
||||
{
|
||||
this.logger.LogCritical(e, $"{nameof(FatalException)} encountered. Closing application");
|
||||
MessageBox.Show(innerFatalException.ToString());
|
||||
File.WriteAllText("crash.log", e.ToString());
|
||||
return false;
|
||||
}
|
||||
else if (e is AggregateException aggregateException)
|
||||
@@ -54,24 +62,33 @@ namespace Daybreak.Launch
|
||||
{
|
||||
/*
|
||||
* Ignore exception caused by browser failing to initialize due to missing window.
|
||||
* Likely caused by switching windows before browser was initialized.
|
||||
* Likely caused by switching views before browser was initialized.
|
||||
*/
|
||||
this.logger.LogError(e, "Failed to initialize browser");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (e.Message.Contains("Invalid window handle.") && e.StackTrace.Contains("CoreWebView2Environment.CreateCoreWebView2ControllerAsync"))
|
||||
{
|
||||
/*
|
||||
* Ignore exception caused by browser failing to initialize due to missing window.
|
||||
* Likely caused by switching views before the browser was initialized.
|
||||
*/
|
||||
this.logger.LogError(e, "Failed to initialize browser");
|
||||
return true;
|
||||
}
|
||||
|
||||
this.logger.LogError(e, $"Unhandled exception caught {e.GetType()}");
|
||||
MessageBox.Show(e.ToString());
|
||||
return true;
|
||||
}
|
||||
protected override void ApplicationStarting()
|
||||
{
|
||||
ApplicationServiceManager = this.ServiceManager;
|
||||
this.ServiceManager.GetService<IApplicationLifetimeManager>().OnStartup();
|
||||
this.logger = this.ServiceManager.GetService<ILogger<Launcher>>();
|
||||
this.RegisterViewContainer();
|
||||
}
|
||||
protected override void ApplicationClosing()
|
||||
{
|
||||
this.ServiceManager.GetService<IApplicationLifetimeManager>().OnClosing();
|
||||
}
|
||||
|
||||
private void RegisterViewContainer()
|
||||
|
||||
@@ -86,15 +86,18 @@
|
||||
HorizontalAlignment="Right" Margin="0, 0, 20, 30" FontSize="22" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Clicked="CreditTextBox_MouseLeftButtonDown" Cursor="Hand"></controls:OpaqueButton>
|
||||
<WrapPanel Grid.Row="1" Margin="0, 0, 20, 10" VerticalAlignment="Bottom" HorizontalAlignment="Right">
|
||||
<TextBox Grid.Row="1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Opacity="0.6"
|
||||
Text="{Binding ElementName=_this, Path=CurrentVersionText, Mode=OneWay}" IsReadOnly="True" FontSize="10"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></TextBox>
|
||||
<TextBox Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
<controls:OpaqueButton Grid.Row="1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Opacity="0.6"
|
||||
Text="{Binding ElementName=_this, Path=CurrentVersionText, Mode=OneWay}" FontSize="10"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Clicked="VersionText_Clicked"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Opacity="0.6" Text=" - " FontSize="10" BorderBrush="Transparent" BorderThickness="0"
|
||||
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></TextBox>
|
||||
<TextBox Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Clicked="VersionText_Clicked"></controls:OpaqueButton>
|
||||
<controls:OpaqueButton Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Opacity="0.6" Text="[Admin]" FontSize="10" BorderBrush="Transparent" BorderThickness="0"
|
||||
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></TextBox>
|
||||
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Clicked="VersionText_Clicked"></controls:OpaqueButton>
|
||||
</WrapPanel>
|
||||
<Grid x:Name="Container" Grid.Row="1">
|
||||
</Grid>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Runtime;
|
||||
using Daybreak.Services.Screenshots;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
@@ -31,6 +32,7 @@ namespace Daybreak.Launch
|
||||
private readonly IBloogumClient bloogumClient;
|
||||
private readonly IApplicationUpdater applicationUpdater;
|
||||
private readonly IPrivilegeManager privilegeManager;
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly CancellationTokenSource cancellationToken = new();
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
@@ -45,18 +47,21 @@ namespace Daybreak.Launch
|
||||
IScreenshotProvider screenshotProvider,
|
||||
IBloogumClient bloogumClient,
|
||||
IApplicationUpdater applicationUpdater,
|
||||
IPrivilegeManager privilegeManager)
|
||||
IPrivilegeManager privilegeManager,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions)
|
||||
{
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.screenshotProvider = screenshotProvider.ThrowIfNull(nameof(screenshotProvider));
|
||||
this.bloogumClient = bloogumClient.ThrowIfNull(nameof(bloogumClient));
|
||||
this.applicationUpdater = applicationUpdater.ThrowIfNull(nameof(applicationUpdater));
|
||||
this.privilegeManager = privilegeManager.ThrowIfNull(nameof(privilegeManager));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.InitializeComponent();
|
||||
this.CurrentVersionText = this.applicationUpdater.CurrentVersion;
|
||||
this.CurrentVersionText = this.applicationUpdater.CurrentVersion.ToString();
|
||||
this.IsRunningAsAdmin = this.privilegeManager.AdminPrivileges;
|
||||
}
|
||||
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.SetupImageCycle();
|
||||
@@ -139,6 +144,11 @@ namespace Daybreak.Launch
|
||||
}
|
||||
}
|
||||
|
||||
private void VersionText_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<VersionManagementView>();
|
||||
}
|
||||
|
||||
private void SetImage(ImageSource imageSource)
|
||||
{
|
||||
this.ImageViewer.ShowImage(imageSource);
|
||||
@@ -159,7 +169,7 @@ namespace Daybreak.Launch
|
||||
|
||||
private async void CheckForUpdates()
|
||||
{
|
||||
var updateAvailable = await this.applicationUpdater.UpdateAvailable().ConfigureAwait(true);
|
||||
var updateAvailable = this.liveOptions.Value.AutoCheckUpdate is true && await this.applicationUpdater.UpdateAvailable().ConfigureAwait(true);
|
||||
if (updateAvailable)
|
||||
{
|
||||
this.viewManager.ShowView<AskUpdateView>();
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Models.Github
|
||||
{
|
||||
public sealed class GithubRefTag
|
||||
{
|
||||
[JsonProperty("ref")]
|
||||
public string Ref;
|
||||
[JsonProperty("node_id")]
|
||||
public string NodeId;
|
||||
[JsonProperty("url")]
|
||||
public string Url;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public class Log
|
||||
public sealed class Log
|
||||
{
|
||||
public LogLevel LogLevel { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string StackTrace { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public string Category { get; set; }
|
||||
public LogLevel LogLevel { get; set; }
|
||||
public string CorrelationVector { get; set; }
|
||||
public string EventId { get; set; }
|
||||
public DateTime LogTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public enum LogLevel
|
||||
{
|
||||
Information,
|
||||
Warning,
|
||||
Error,
|
||||
Critical
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Microsoft.CorrelationVector;
|
||||
|
||||
namespace Daybreak.Models
|
||||
{
|
||||
public class ScopeMetadata
|
||||
{
|
||||
public CorrelationVector CorrelationVector { get; set; }
|
||||
|
||||
public ScopeMetadata(CorrelationVector correlationVector)
|
||||
{
|
||||
this.CorrelationVector = correlationVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,11 @@ namespace Daybreak.Models
|
||||
public sealed class UpdateStatus : INotifyPropertyChanged
|
||||
{
|
||||
public static readonly UpdateStep StartingStep = new("Starting");
|
||||
public static readonly UpdateStep InitializingDownload = new("Initializing download");
|
||||
public static readonly UpdateStep CheckingLatestVersion = new("Checking latest version");
|
||||
public static UpdateStep Downloading(double progress) => new DownloadUpdateStep("Downloading", progress);
|
||||
public static readonly UpdateStep DownloadFinished = new("Download finished. Application will restart in order to apply the update.");
|
||||
public static readonly UpdateStep DownloadFinished = new("Download finished. Application will restart in order to apply the update");
|
||||
public static readonly UpdateStep FailedDownload = new("Update failed. Please check logs for details");
|
||||
|
||||
private UpdateStep currentStep = StartingStep;
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Models.Versioning
|
||||
{
|
||||
public sealed class Version
|
||||
{
|
||||
private List<VersionToken> parts = new();
|
||||
|
||||
public bool HasPrefix { get; private set; }
|
||||
public IEnumerable<VersionToken> VersionTokens { get => this.parts; }
|
||||
public string VersionString { get => this.ToString(); }
|
||||
|
||||
private Version()
|
||||
{
|
||||
}
|
||||
|
||||
public Version(string version)
|
||||
{
|
||||
if (TryParseParts(version, out var parts, out var hasPrefix) is false)
|
||||
{
|
||||
throw new ArgumentException($"Provided argument is not valid: {version}");
|
||||
}
|
||||
|
||||
this.parts = parts;
|
||||
this.HasPrefix = hasPrefix;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var version = string.Join('.', parts.OfType<VersionNumberToken>());
|
||||
if (parts.Last() is VersionStringToken)
|
||||
{
|
||||
version += "-" + parts.Last();
|
||||
}
|
||||
|
||||
if (this.HasPrefix)
|
||||
{
|
||||
version = 'v' + version;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public static Version Parse(string version)
|
||||
{
|
||||
if (TryParse(version, out var parsedVersion) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to parse version: {version}");
|
||||
}
|
||||
|
||||
return parsedVersion;
|
||||
}
|
||||
|
||||
public static bool TryParse(string version, out Version parsedVersion)
|
||||
{
|
||||
if (TryParseParts(version, out var parts, out var hasPrefix) is false)
|
||||
{
|
||||
parsedVersion = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = parts.Count - 1; i >= 1; i--)
|
||||
{
|
||||
if (parts[i] is VersionNumberToken && parts[i].ToString() == "0")
|
||||
{
|
||||
parts.RemoveAt(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parsedVersion = new Version
|
||||
{
|
||||
parts = parts,
|
||||
HasPrefix = hasPrefix
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryParseParts(string version, out List<VersionToken> parts, out bool hasPrefix)
|
||||
{
|
||||
hasPrefix = false;
|
||||
parts = null;
|
||||
if (version.IsNullOrWhiteSpace())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version.StartsWith('.') || version.EndsWith('.'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var tokens = version.Trim().Split('.');
|
||||
if (tokens.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tokens[0].StartsWith('v'))
|
||||
{
|
||||
hasPrefix = true;
|
||||
tokens[0] = tokens[0][1..];
|
||||
}
|
||||
|
||||
parts = new List<VersionToken>();
|
||||
for(int i = 0; i < tokens.Length - 1; i++)
|
||||
{
|
||||
var token = tokens[i];
|
||||
if (token.IsNullOrWhiteSpace() || token.All(c => char.IsDigit(c)) is false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
parts.Add(VersionToken.Parse(token));
|
||||
}
|
||||
|
||||
var lastToken = tokens[^1];
|
||||
if (lastToken.Contains('-'))
|
||||
{
|
||||
var lastTokenParts = lastToken.Split('-');
|
||||
if (lastTokenParts.Length > 2 || lastTokenParts.Length < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lastTokenParts[0].IsNullOrWhiteSpace() || lastTokenParts[0].All(c => char.IsDigit(c)) is false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
parts.Add(VersionToken.Parse(lastTokenParts[0]));
|
||||
if (lastTokenParts[1].IsNullOrWhiteSpace() || lastTokenParts[1].All(c => char.IsLetter(c)) is false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
parts.Add(VersionToken.Parse(lastTokenParts[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastToken.IsNullOrWhiteSpace() || lastToken.Any(c => char.IsDigit(c) is false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
parts.Add(VersionToken.Parse(lastToken));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Daybreak.Models.Versioning
|
||||
{
|
||||
public sealed class VersionNumberToken : VersionToken
|
||||
{
|
||||
public int Number { get; }
|
||||
internal VersionNumberToken(int number)
|
||||
{
|
||||
this.Number = number;
|
||||
}
|
||||
|
||||
protected override string Stringify()
|
||||
{
|
||||
return this.Number.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Daybreak.Models.Versioning
|
||||
{
|
||||
public sealed class VersionStringToken : VersionToken
|
||||
{
|
||||
public string Token { get; }
|
||||
internal VersionStringToken(string token)
|
||||
{
|
||||
this.Token = token;
|
||||
}
|
||||
|
||||
protected override string Stringify()
|
||||
{
|
||||
return this.Token;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Models.Versioning
|
||||
{
|
||||
public abstract class VersionToken
|
||||
{
|
||||
public static VersionToken Parse(string token)
|
||||
{
|
||||
if (token.All(c => char.IsDigit(c)))
|
||||
{
|
||||
var number = int.Parse(token);
|
||||
return new VersionNumberToken(number);
|
||||
}
|
||||
|
||||
if (token.All(c => char.IsLetter(c)))
|
||||
{
|
||||
return new VersionStringToken(token);
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Failed to parse version token {token}");
|
||||
}
|
||||
|
||||
protected abstract string Stringify();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Stringify();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.Logging;
|
||||
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;
|
||||
@@ -18,6 +18,7 @@ using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Services.ApplicationLauncher
|
||||
{
|
||||
@@ -30,10 +31,10 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
private const string ProcessName = "gw";
|
||||
private const string ArenaNetMutex = "AN-Mute";
|
||||
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly ICredentialManager credentialManager;
|
||||
private readonly IMutexHandler mutexHandler;
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<ApplicationLauncher> logger;
|
||||
private readonly IPrivilegeManager privilegeManager;
|
||||
|
||||
public bool IsTexmodRunning => TexModProcessDetected();
|
||||
@@ -41,22 +42,22 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
public bool IsToolboxRunning => GuildwarsToolboxProcessDetected();
|
||||
|
||||
public ApplicationLauncher(
|
||||
IConfigurationManager configurationManager,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
ICredentialManager credentialManager,
|
||||
IMutexHandler mutexHandler,
|
||||
ILogger logger,
|
||||
ILogger<ApplicationLauncher> logger,
|
||||
IPrivilegeManager privilegeManager)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.mutexHandler = mutexHandler.ThrowIfNull(nameof(mutexHandler));
|
||||
this.credentialManager = credentialManager.ThrowIfNull(nameof(credentialManager));
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.privilegeManager = privilegeManager.ThrowIfNull(nameof(privilegeManager));
|
||||
}
|
||||
|
||||
public async Task<bool> LaunchGuildwars()
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var configuration = this.liveOptions.Value;
|
||||
var auth = await this.credentialManager.GetDefaultCredentials().ConfigureAwait(false);
|
||||
return await auth.Switch(
|
||||
onSome: async (credentials) =>
|
||||
@@ -85,7 +86,7 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var configuration = this.liveOptions.Value;
|
||||
var executable = configuration.ToolboxPath;
|
||||
if (File.Exists(executable) is false)
|
||||
{
|
||||
@@ -103,7 +104,7 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var configuration = this.configurationManager.GetConfiguration();
|
||||
var configuration = this.liveOptions.Value;
|
||||
var executable = configuration.TexmodPath;
|
||||
if (File.Exists(executable) is false)
|
||||
{
|
||||
@@ -146,7 +147,7 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
|
||||
private async Task<bool> LaunchGuildwarsProcess(string email, Models.SecureString password, string character)
|
||||
{
|
||||
var executable = this.configurationManager.GetConfiguration().GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
var executable = this.liveOptions.Value.GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
if (executable is null)
|
||||
{
|
||||
throw new ExecutableNotFoundException($"No executable selected");
|
||||
@@ -170,7 +171,7 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
args.Add(character);
|
||||
}
|
||||
|
||||
var identity = this.configurationManager.GetConfiguration().ExperimentalFeatures.LaunchGuildwarsAsCurrentUser ?
|
||||
var identity = this.liveOptions.Value.ExperimentalFeatures.LaunchGuildwarsAsCurrentUser ?
|
||||
System.Security.Principal.WindowsIdentity.GetCurrent().Name :
|
||||
System.Security.Principal.WindowsIdentity.GetAnonymous().Name;
|
||||
this.logger.LogInformation($"Launching guildwars as [{identity}] identity");
|
||||
@@ -222,11 +223,11 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
|
||||
private bool GuildwarsProcessDetected()
|
||||
{
|
||||
if (this.configurationManager.GetConfiguration().ExperimentalFeatures.MultiLaunchSupport is true)
|
||||
if (this.liveOptions.Value.ExperimentalFeatures.MultiLaunchSupport is true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = this.configurationManager.GetConfiguration().GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
var path = this.liveOptions.Value.GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
if (path is null)
|
||||
{
|
||||
return false;
|
||||
@@ -254,7 +255,7 @@ namespace Daybreak.Services.ApplicationLauncher
|
||||
|
||||
private void SetRegistryGuildwarsPath()
|
||||
{
|
||||
var path = this.configurationManager.GetConfiguration().GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
var path = this.liveOptions.Value.GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
|
||||
if (path is null)
|
||||
{
|
||||
throw new ExecutableNotFoundException("No executable currently selected");
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using IServiceProvider = Slim.IServiceProvider;
|
||||
|
||||
namespace Daybreak.Services.ApplicationLifetime
|
||||
{
|
||||
public sealed class ApplicationLifetimeManager : IApplicationLifetimeManager
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private List<Type> RegisteredTypes { get; } = new List<Type>();
|
||||
|
||||
public ApplicationLifetimeManager(IServiceProvider serviceProvider)
|
||||
{
|
||||
serviceProvider.ThrowIfNull(nameof(serviceProvider));
|
||||
|
||||
this.serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public void RegisterService<T>() where T : IApplicationLifetimeService
|
||||
{
|
||||
this.RegisteredTypes.Add(typeof(T));
|
||||
}
|
||||
|
||||
public void OnStartup()
|
||||
{
|
||||
foreach (var serviceType in this.RegisteredTypes)
|
||||
{
|
||||
var service = this.serviceProvider.GetService(serviceType);
|
||||
service.As<IApplicationLifetimeService>().OnStartup();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClosing()
|
||||
{
|
||||
foreach (var serviceType in this.RegisteredTypes)
|
||||
{
|
||||
var service = this.serviceProvider.GetService(serviceType);
|
||||
service.As<IApplicationLifetimeService>().OnClosing();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Daybreak.Services.ApplicationLifetime
|
||||
{
|
||||
public interface IApplicationLifetimeManager : IApplicationLifetimeProducer
|
||||
{
|
||||
void OnStartup();
|
||||
void OnClosing();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Daybreak.Services.ApplicationLifetime
|
||||
{
|
||||
public interface IApplicationLifetimeProducer
|
||||
{
|
||||
void RegisterService<T>() where T : IApplicationLifetimeService;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Daybreak.Services.ApplicationLifetime
|
||||
{
|
||||
public interface IApplicationLifetimeService
|
||||
{
|
||||
void OnStartup();
|
||||
void OnClosing();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using Daybreak.Services.Bloogum.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Http;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Daybreak.Services.Bloogum
|
||||
@@ -12,15 +11,16 @@ namespace Daybreak.Services.Bloogum
|
||||
public sealed class BloogumClient : IBloogumClient
|
||||
{
|
||||
private const string BaseAddress = "http://bloogum.net/guildwars";
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly IHttpClient<BloogumClient> httpClient;
|
||||
private readonly ILogger logger;
|
||||
private readonly Random random = new();
|
||||
|
||||
public BloogumClient(ILogger logger)
|
||||
public BloogumClient(
|
||||
ILogger<BloogumClient> logger,
|
||||
IHttpClient<BloogumClient> httpClient)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
|
||||
this.httpClient = new HttpClient();
|
||||
this.httpClient = httpClient.ThrowIfNull(nameof(httpClient));
|
||||
}
|
||||
|
||||
public async Task<Optional<Stream>> GetRandomScreenShot()
|
||||
@@ -53,7 +53,7 @@ namespace Daybreak.Services.Bloogum
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
this.logger.LogError(e);
|
||||
this.logger.LogError(e.ToString());
|
||||
return Optional.None<Stream>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,13 +81,13 @@ namespace Daybreak.Services.Bloogum.Models
|
||||
new Category("stingraystrand", 15),
|
||||
new Category("fishermenshaven", 4),
|
||||
new Category("riversideprovince", 31),
|
||||
new Category("sanctumcay", 21)
|
||||
new Category("sanctumcay", 21),
|
||||
new Category("majestysrest", 14)
|
||||
});
|
||||
public static readonly Location MaguumaJungle = new(
|
||||
"maguuma",
|
||||
new List<Category>
|
||||
{
|
||||
new Category("majestysrest", 14),
|
||||
new Category("druidsoverlook", 1),
|
||||
new Category("sagelands", 27),
|
||||
new Category("thewilds", 19),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
@@ -16,10 +15,10 @@ namespace Daybreak.Services.BuildTemplates
|
||||
private const string DecodingLookupTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
private readonly static string BuildsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Guild Wars\\Templates\\Skills";
|
||||
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<BuildTemplateManager> logger;
|
||||
|
||||
public BuildTemplateManager(
|
||||
ILogger logger)
|
||||
ILogger<BuildTemplateManager> logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
}
|
||||
@@ -229,8 +228,10 @@ namespace Daybreak.Services.BuildTemplates
|
||||
{
|
||||
var curedTemplate = template.Trim();
|
||||
|
||||
var buildMetadata = new BuildMetadata();
|
||||
buildMetadata.Base64Decoded = template.Select(c => DecodingLookupTable.IndexOf(c)).ToList();
|
||||
var buildMetadata = new BuildMetadata
|
||||
{
|
||||
Base64Decoded = template.Select(c => DecodingLookupTable.IndexOf(c)).ToList(),
|
||||
};
|
||||
buildMetadata.BinaryDecoded = buildMetadata.Base64Decoded.Select(b => ToBitString(b)).ToList();
|
||||
|
||||
var stream = new DecodeCharStream(buildMetadata.BinaryDecoded.ToArray());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
@@ -12,11 +12,11 @@ namespace Daybreak.Services.Configuration
|
||||
private const string ConfigName = "Daybreak.config.json";
|
||||
|
||||
private ApplicationConfiguration applicationConfiguration;
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<ConfigurationManager> logger;
|
||||
|
||||
public event EventHandler ConfigurationChanged;
|
||||
|
||||
public ConfigurationManager(ILogger logger)
|
||||
public ConfigurationManager(ILogger<ConfigurationManager> logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
try
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
@@ -9,20 +9,21 @@ using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Services.Credentials
|
||||
{
|
||||
public sealed class CredentialManager : ICredentialManager
|
||||
{
|
||||
private static readonly byte[] Entropy = Convert.FromBase64String("R3VpbGR3YXJz");
|
||||
private readonly ILogger logger;
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILogger<CredentialManager> logger;
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveOptions;
|
||||
|
||||
public CredentialManager(
|
||||
ILogger logger,
|
||||
IConfigurationManager configurationManager)
|
||||
ILogger<CredentialManager> logger,
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveOptions)
|
||||
{
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
}
|
||||
|
||||
@@ -54,7 +55,7 @@ namespace Daybreak.Services.Credentials
|
||||
return Task.Run(() =>
|
||||
{
|
||||
this.logger.LogInformation("Retrieving credentials");
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
var config = this.liveOptions.Value;
|
||||
if (config.ProtectedLoginCredentials is null || config.ProtectedLoginCredentials.Count == 0)
|
||||
{
|
||||
this.logger.LogInformation("No credentials found");
|
||||
@@ -74,13 +75,12 @@ namespace Daybreak.Services.Credentials
|
||||
return Task.Run(() =>
|
||||
{
|
||||
this.logger.LogInformation("Storing credentials");
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
config.ProtectedLoginCredentials = loginCredentials
|
||||
this.liveOptions.Value.ProtectedLoginCredentials = loginCredentials
|
||||
.Select(ProtectCredentials)
|
||||
.Where(CredentialsProtected)
|
||||
.Select(ExtractProtectedCredentials)
|
||||
.ToList();
|
||||
this.configurationManager.SaveConfiguration(config);
|
||||
this.liveOptions.UpdateOption();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.Configuration;
|
||||
using HtmlAgilityPack;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Http;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Services.IconRetrieve
|
||||
{
|
||||
@@ -16,18 +18,48 @@ namespace Daybreak.Services.IconRetrieve
|
||||
private const string NamePlaceholder = "[SKILLNAME]";
|
||||
private const string BaseUrl = "https://wiki.guildwars.com";
|
||||
private const string QueryUrl = $"wiki/File:{NamePlaceholder}.jpg";
|
||||
private const string IconsDirectoryName = "Icons";
|
||||
private const string IconsLocation = $"{IconsDirectoryName}/{NamePlaceholder}.jpg";
|
||||
|
||||
private readonly HttpClient httpClient = new();
|
||||
private readonly ILogger logger;
|
||||
private readonly IHttpClient<IconRetriever> httpClient;
|
||||
private readonly ILogger<IconRetriever> logger;
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
|
||||
public IconRetriever(
|
||||
ILogger logger)
|
||||
ILogger<IconRetriever> logger,
|
||||
IHttpClient<IconRetriever> httpClient,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.httpClient = httpClient.ThrowIfNull(nameof(httpClient));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.httpClient.BaseAddress = new Uri(BaseUrl);
|
||||
if (Directory.Exists(IconsDirectoryName) is false)
|
||||
{
|
||||
Directory.CreateDirectory(IconsDirectoryName);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Optional<Stream>> GetIcon(Skill skill)
|
||||
{
|
||||
if (this.liveOptions.Value.KeepLocalIconCache)
|
||||
{
|
||||
this.logger.LogInformation($"{nameof(IconRetriever)} configured to look first in cache before downloading icons");
|
||||
var maybeIcon = await this.GetLocalIcon(skill);
|
||||
if (maybeIcon.ExtractValue() is Stream stream)
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.logger.LogInformation($"{nameof(IconRetriever)} configured to skip local cache. Downloading icon");
|
||||
}
|
||||
|
||||
return await this.DownloadIcon(skill);
|
||||
}
|
||||
|
||||
private async Task<Optional<Stream>> DownloadIcon(Skill skill)
|
||||
{
|
||||
var curedSkillName = skill.Name
|
||||
.Replace(" ", "_");
|
||||
@@ -55,13 +87,42 @@ namespace Daybreak.Services.IconRetrieve
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
this.logger.LogInformation("Retrieved latest icon stream");
|
||||
return new MemoryStream(await iconResponse.Content.ReadAsByteArrayAsync());
|
||||
var iconData = await iconResponse.Content.ReadAsByteArrayAsync();
|
||||
if (this.liveOptions.Value.KeepLocalIconCache)
|
||||
{
|
||||
await SaveIconLocally(skill, iconData);
|
||||
}
|
||||
return new MemoryStream(iconData);
|
||||
}
|
||||
|
||||
this.logger.LogError($"Failed to retrieve icon from {BaseUrl + "/" + url}");
|
||||
return Optional.None<Stream>();
|
||||
}
|
||||
|
||||
private async Task<Optional<Stream>> GetLocalIcon(Skill skill)
|
||||
{
|
||||
var curedSkillName = skill.Name
|
||||
.Replace(" ", "_")
|
||||
.Replace("\"", "");
|
||||
this.logger.LogInformation("Checking local icon cache");
|
||||
if (File.Exists(IconsLocation.Replace(NamePlaceholder, curedSkillName)))
|
||||
{
|
||||
this.logger.LogInformation("Local icon cache found. Retrieving icon");
|
||||
return new MemoryStream(await File.ReadAllBytesAsync(IconsLocation.Replace(NamePlaceholder, curedSkillName)));
|
||||
}
|
||||
|
||||
this.logger.LogWarning("No local icon cache found");
|
||||
return Optional.None<Stream>();
|
||||
}
|
||||
|
||||
private static async Task SaveIconLocally(Skill skill, byte[] data)
|
||||
{
|
||||
var curedSkillName = skill.Name
|
||||
.Replace(" ", "_")
|
||||
.Replace("\"", "");
|
||||
await File.WriteAllBytesAsync(IconsLocation.Replace(NamePlaceholder, curedSkillName), data);
|
||||
}
|
||||
|
||||
private static string GetHref(HtmlDocument doc)
|
||||
{
|
||||
foreach (var child in doc.DocumentNode.Descendants("a"))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using System;
|
||||
using System.Windows.Extensions.Services;
|
||||
|
||||
namespace Daybreak.Services.KeyboardHook
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
@@ -15,7 +14,7 @@ namespace Daybreak.Services.KeyboardHook
|
||||
// https://stackoverflow.com/questions/604410/global-keyboard-capture-in-c-sharp-application
|
||||
public sealed class KeyboardHookService : IKeyboardHookService, IDisposable
|
||||
{
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<KeyboardHookService> logger;
|
||||
private IntPtr windowsHookHandle;
|
||||
private IntPtr user32LibraryHandle;
|
||||
private NativeMethods.HookProc hookProc;
|
||||
@@ -23,7 +22,7 @@ namespace Daybreak.Services.KeyboardHook
|
||||
public event EventHandler<KeyboardHookEventArgs> KeyboardPressed;
|
||||
|
||||
public KeyboardHookService(
|
||||
ILogger logger)
|
||||
ILogger<KeyboardHookService> logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.Setup();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using System.Windows.Extensions.Services;
|
||||
|
||||
namespace Daybreak.Services.KeyboardMacros
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.KeyboardHook;
|
||||
using Daybreak.Services.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -9,6 +10,7 @@ using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Daybreak.Services.KeyboardMacros
|
||||
@@ -16,36 +18,24 @@ namespace Daybreak.Services.KeyboardMacros
|
||||
public sealed class MacroService : IMacroService
|
||||
{
|
||||
private readonly CancellationTokenSource cancellationTokenSource = new();
|
||||
private readonly ILogger logger;
|
||||
private readonly IKeyboardHookService keyboardHookService;
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly HashSet<Keys> KeysDown = new();
|
||||
|
||||
private IEnumerable<KeyMacro> loadedMacros;
|
||||
private bool gameActive, hookEnabled;
|
||||
private bool gameActive;
|
||||
private IntPtr gwWindowHwnd;
|
||||
|
||||
public MacroService(
|
||||
ILogger logger,
|
||||
IKeyboardHookService keyboardHookService,
|
||||
IConfigurationManager configurationManager)
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.keyboardHookService = keyboardHookService.ThrowIfNull(nameof(keyboardHookService));
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
|
||||
this.configurationManager.ConfigurationChanged += (s, e) => this.LoadConfiguration();
|
||||
this.LoadConfiguration();
|
||||
this.keyboardHookService.KeyboardPressed += this.KeyboardHookService_KeyboardPressed;
|
||||
this.SetupGameActiveChecker();
|
||||
}
|
||||
|
||||
private void LoadConfiguration()
|
||||
{
|
||||
this.hookEnabled = this.configurationManager.GetConfiguration().ExperimentalFeatures.CanInterceptKeys;
|
||||
this.loadedMacros = this.configurationManager.GetConfiguration().ExperimentalFeatures.Macros ?? new List<KeyMacro>();
|
||||
}
|
||||
|
||||
private void SetupGameActiveChecker()
|
||||
{
|
||||
TaskExtensions.RunPeriodicAsync(() =>
|
||||
@@ -70,7 +60,7 @@ namespace Daybreak.Services.KeyboardMacros
|
||||
|
||||
private void KeyboardHookService_KeyboardPressed(object sender, KeyboardHookEventArgs e)
|
||||
{
|
||||
if (this.gameActive && this.hookEnabled)
|
||||
if (this.gameActive && this.liveOptions.Value.ExperimentalFeatures.CanInterceptKeys)
|
||||
{
|
||||
if (e.KeyboardState == KeyboardState.KeyDown)
|
||||
{
|
||||
@@ -82,7 +72,7 @@ namespace Daybreak.Services.KeyboardMacros
|
||||
return;
|
||||
}
|
||||
|
||||
e.Handled = this.loadedMacros
|
||||
e.Handled = this.liveOptions.Value.ExperimentalFeatures.Macros
|
||||
.Where(keyMacro => MacroContainsKey(keyMacro, e.KeyboardInput.Key))
|
||||
.Where(this.MacroHit)
|
||||
.Do(this.HandleMacro)
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Daybreak.Services.Logging
|
||||
{
|
||||
public class FlatLoggingDatabase : ILoggingDatabase
|
||||
{
|
||||
private const string Path = "logs.db";
|
||||
private const int bufferSize = 10;
|
||||
private const char separator = '§';
|
||||
private readonly string filePath = Path;
|
||||
private readonly List<string> buffer = new List<string>();
|
||||
|
||||
public FlatLoggingDatabase()
|
||||
{
|
||||
}
|
||||
|
||||
public Task<IEnumerable<Log>> GetLogs()
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
lock (this.buffer)
|
||||
{
|
||||
if (this.buffer.Count > 0)
|
||||
{
|
||||
this.WriteBufferToFile();
|
||||
}
|
||||
}
|
||||
|
||||
return this.GetSerializedLogs().Select(s => s.Deserialize<Log>());
|
||||
});
|
||||
}
|
||||
|
||||
public Task<IEnumerable<Log>> GetLogsByDate(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
lock (this.buffer)
|
||||
{
|
||||
if (this.buffer.Count > 0)
|
||||
{
|
||||
this.WriteBufferToFile();
|
||||
}
|
||||
}
|
||||
|
||||
return this.GetSerializedLogs()
|
||||
.Select(s => s.Deserialize<Log>())
|
||||
.Where(l => l.Timestamp > startTime && l.Timestamp < endTime);
|
||||
});
|
||||
}
|
||||
|
||||
public Task<bool> InsertLog(Log log)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
lock (this.buffer)
|
||||
{
|
||||
this.buffer.Add(log.Serialize());
|
||||
|
||||
if (this.buffer.Count > bufferSize)
|
||||
{
|
||||
this.WriteBufferToFile();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public Task<bool> ClearDatabase()
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
lock (this.buffer)
|
||||
{
|
||||
this.buffer.Clear();
|
||||
}
|
||||
lock (this.filePath)
|
||||
{
|
||||
File.WriteAllText(this.filePath, string.Empty);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void OnClosing()
|
||||
{
|
||||
this.WriteBufferToFile();
|
||||
}
|
||||
|
||||
public void OnStartup()
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var fs = File.Create(filePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FatalException("Could not initialize logging. See inner exception for details.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteBufferToFile()
|
||||
{
|
||||
lock (this.filePath)
|
||||
{
|
||||
File.AppendAllLines(this.filePath, this.buffer.Select(s => s + separator), Encoding.UTF8);
|
||||
}
|
||||
this.buffer.Clear();
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetSerializedLogs()
|
||||
{
|
||||
lock (this.filePath)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
using var fileStream = File.OpenRead(this.filePath);
|
||||
using var streamReader = new StreamReader(fileStream, Encoding.UTF8);
|
||||
string serializedLog = null;
|
||||
while ((serializedLog = streamReader.ReadUntil(separator.ToString())) != null
|
||||
&& serializedLog != string.Empty
|
||||
&& serializedLog != "\r"
|
||||
&& serializedLog != "\n"
|
||||
&& serializedLog != "\r\n")
|
||||
{
|
||||
yield return serializedLog;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Daybreak.Models;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Services.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Log(LogLevel logLevel, Exception exception);
|
||||
void Log(LogLevel logLevel, string message);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Daybreak.Services.Logging
|
||||
{
|
||||
public interface ILoggingDatabase : IApplicationLifetimeService
|
||||
{
|
||||
Task<bool> ClearDatabase();
|
||||
Task<IEnumerable<Log>> GetLogsByDate(DateTime startTime, DateTime endTime);
|
||||
Task<IEnumerable<Log>> GetLogs();
|
||||
Task<bool> InsertLog(Log log);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Daybreak.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using WpfExtended.Logging;
|
||||
|
||||
namespace Daybreak.Services.Logging
|
||||
{
|
||||
public interface ILogsManager : ILogsWriter
|
||||
{
|
||||
IEnumerable<Log> GetLogs(Expression<Func<Log, bool>> filter);
|
||||
IEnumerable<Log> GetLogs();
|
||||
int DeleteLogs();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using LiteDB;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq.Expressions;
|
||||
using WpfExtended.Models;
|
||||
|
||||
namespace Daybreak.Services.Logging
|
||||
{
|
||||
public sealed class JsonLogsManager : ILogsManager
|
||||
{
|
||||
private readonly ILiteDatabase liteDatabase;
|
||||
|
||||
public JsonLogsManager(ILiteDatabase liteDatabase)
|
||||
{
|
||||
this.liteDatabase = liteDatabase.ThrowIfNull(nameof(liteDatabase));
|
||||
}
|
||||
|
||||
public IEnumerable<Models.Log> GetLogs(Expression<Func<Models.Log, bool>> filter)
|
||||
{
|
||||
return this.liteDatabase.GetCollection<Models.Log>().Find(filter);
|
||||
}
|
||||
public IEnumerable<Models.Log> GetLogs()
|
||||
{
|
||||
return this.liteDatabase.GetCollection<Models.Log>().FindAll();
|
||||
}
|
||||
public void WriteLog(Log log)
|
||||
{
|
||||
var dbLog = new Models.Log
|
||||
{
|
||||
EventId = log.EventId,
|
||||
Message = log.Exception is null ? log.Message : $"{log.Message}{Environment.NewLine}{log.Exception}",
|
||||
Category = log.Category,
|
||||
LogLevel = log.LogLevel,
|
||||
LogTime = log.LogTime,
|
||||
CorrelationVector = log.CorrelationVector
|
||||
};
|
||||
|
||||
this.liteDatabase.GetCollection<Models.Log>().Insert(dbLog);
|
||||
}
|
||||
public int DeleteLogs()
|
||||
{
|
||||
return this.liteDatabase.GetCollection<Models.Log>().DeleteAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Daybreak.Models;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Services.Logging
|
||||
{
|
||||
public class Logger : ILogger
|
||||
{
|
||||
private readonly ILoggingDatabase loggingDatabase;
|
||||
public Logger(ILoggingDatabase loggingDatabase)
|
||||
{
|
||||
this.loggingDatabase = loggingDatabase;
|
||||
}
|
||||
|
||||
public async void Log(LogLevel logLevel, Exception exception)
|
||||
{
|
||||
if (exception is null) throw new ArgumentNullException(nameof(exception));
|
||||
|
||||
await this.loggingDatabase.InsertLog(
|
||||
new Log
|
||||
{
|
||||
LogLevel = logLevel,
|
||||
Message = exception.Message,
|
||||
StackTrace = exception.StackTrace,
|
||||
Timestamp = DateTime.Now
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async void Log(LogLevel logLevel, string message)
|
||||
{
|
||||
if (message is null) throw new ArgumentNullException(nameof(message));
|
||||
|
||||
await this.loggingDatabase.InsertLog(
|
||||
new Log
|
||||
{
|
||||
LogLevel = logLevel,
|
||||
Message = message,
|
||||
StackTrace = Environment.StackTrace,
|
||||
Timestamp = DateTime.Now
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using Slim;
|
||||
using Daybreak.Models;
|
||||
using Microsoft.CorrelationVector;
|
||||
using Slim;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows;
|
||||
@@ -53,9 +55,11 @@ namespace Daybreak.Services.ViewManagement
|
||||
|
||||
private void ShowViewInner(Type viewType, object dataContext)
|
||||
{
|
||||
var scopedManager = this.serviceManager.CreateScope();
|
||||
scopedManager.As<IServiceManager>().RegisterScoped<ScopeMetadata, ScopeMetadata>((sp) => new ScopeMetadata(new CorrelationVector()));
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var view = this.serviceManager.GetService(viewType).As<UserControl>();
|
||||
var view = scopedManager.GetService(viewType).As<UserControl>();
|
||||
this.container.Children.Clear();
|
||||
this.container.Children.Add(view);
|
||||
view.DataContext = dataContext;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Configuration;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Services.Options
|
||||
{
|
||||
public sealed class ApplicationConfigurationOptionsManager : IOptionsManager
|
||||
{
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
|
||||
public ApplicationConfigurationOptionsManager(IConfigurationManager configurationManager)
|
||||
{
|
||||
this.configurationManager = configurationManager;
|
||||
}
|
||||
|
||||
public T GetOptions<T>() where T : class
|
||||
{
|
||||
if (typeof(T) == typeof(ApplicationConfiguration))
|
||||
{
|
||||
return this.configurationManager.GetConfiguration().Cast<T>();
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"{nameof(ApplicationConfigurationOptionsManager)} cannot return options of type {typeof(T).Name}");
|
||||
}
|
||||
|
||||
public void UpdateOptions<T>(T value) where T : class
|
||||
{
|
||||
if (typeof(T) == typeof(ApplicationConfiguration))
|
||||
{
|
||||
this.configurationManager.SaveConfiguration(value.Cast<ApplicationConfiguration>());
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"{nameof(ApplicationConfigurationOptionsManager)} cannot save options of type {typeof(T).Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
using System.Security.Principal;
|
||||
using System.Windows.Controls;
|
||||
@@ -14,11 +13,11 @@ namespace Daybreak.Services.Privilege
|
||||
public bool AdminPrivileges => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
||||
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<PrivilegeManager> logger;
|
||||
|
||||
public PrivilegeManager(
|
||||
IViewManager viewManager,
|
||||
ILogger logger)
|
||||
ILogger<PrivilegeManager> logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Daybreak.Services.Runtime
|
||||
{
|
||||
public interface IRuntimeStore
|
||||
{
|
||||
void StoreValue<T>(string name, T value);
|
||||
bool TryGetValue<T>(string name, out T value);
|
||||
T GetValue<T>(string name);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
|
||||
namespace Daybreak.Services.Runtime
|
||||
{
|
||||
public sealed class RuntimeStore : IRuntimeStore
|
||||
{
|
||||
private Dictionary<string, object> InnerStore { get; } = new Dictionary<string, object>();
|
||||
|
||||
public T GetValue<T>(string name)
|
||||
{
|
||||
if(this.InnerStore.TryGetValue(name, out var value))
|
||||
{
|
||||
return value.Cast<T>();
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Could not find any value stored with name {name}");
|
||||
}
|
||||
public void StoreValue<T>(string name, T value)
|
||||
{
|
||||
this.InnerStore[name] = value;
|
||||
}
|
||||
public bool TryGetValue<T>(string name, out T value)
|
||||
{
|
||||
if (this.InnerStore.TryGetValue(name, out var valueObj))
|
||||
{
|
||||
value = valueObj.Cast<T>();
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Pepa.Wpf.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -12,13 +11,13 @@ namespace Daybreak.Services.Screens
|
||||
{
|
||||
public sealed class ScreenManager : IScreenManager
|
||||
{
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<ScreenManager> logger;
|
||||
|
||||
public IEnumerable<Screen> Screens { get; } = WpfScreenHelper.Screen.AllScreens
|
||||
.Select((screen, index) => new Screen { Id = index, Size = screen.Bounds });
|
||||
|
||||
public ScreenManager(
|
||||
ILogger logger)
|
||||
ILogger<ScreenManager> logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using System.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Windows.Extensions.Services;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Services.Screenshots
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
@@ -14,11 +13,11 @@ namespace Daybreak.Services.Screenshots
|
||||
{
|
||||
private const string ScreenshotsFolder = "Screenshots";
|
||||
|
||||
private readonly List<string> Screenshots = new List<string>();
|
||||
private readonly ILogger logger;
|
||||
private readonly List<string> Screenshots = new();
|
||||
private readonly ILogger<ScreenshotProvider> logger;
|
||||
private int innerCount = 0;
|
||||
|
||||
public ScreenshotProvider(ILogger logger)
|
||||
public ScreenshotProvider(ILogger<ScreenshotProvider> logger)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
if (Directory.Exists(ScreenshotsFolder) is false)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using System.Windows.Extensions.Services;
|
||||
|
||||
namespace Daybreak.Services.Shortcuts
|
||||
{
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Configuration;
|
||||
using ShellLink;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Services.Shortcuts
|
||||
{
|
||||
//TODO: Fix dependency on IConfigurationManager
|
||||
public sealed class ShortcutManager : IShortcutManager
|
||||
{
|
||||
private const string ShortcutName = "Daybreak.lnk";
|
||||
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
|
||||
public bool ShortcutEnabled {
|
||||
get => this.ShortcutExists();
|
||||
@@ -27,16 +31,19 @@ namespace Daybreak.Services.Shortcuts
|
||||
}
|
||||
}
|
||||
|
||||
public ShortcutManager(IConfigurationManager configurationManager)
|
||||
public ShortcutManager(
|
||||
IConfigurationManager configurationManager,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions)
|
||||
{
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.configurationManager.ConfigurationChanged += (_, _) => this.LoadConfiguration();
|
||||
this.LoadConfiguration();
|
||||
}
|
||||
|
||||
private void LoadConfiguration()
|
||||
{
|
||||
var shortcutEnabled = this.configurationManager.GetConfiguration().PlaceShortcut;
|
||||
var shortcutEnabled = this.liveOptions.Value.PlaceShortcut;
|
||||
if (shortcutEnabled && this.ShortcutEnabled is false)
|
||||
{
|
||||
this.ShortcutEnabled = true;
|
||||
@@ -49,7 +56,7 @@ namespace Daybreak.Services.Shortcuts
|
||||
|
||||
private bool ShortcutExists()
|
||||
{
|
||||
var shortcutFolder = this.configurationManager.GetConfiguration().ShortcutLocation;
|
||||
var shortcutFolder = this.liveOptions.Value.ShortcutLocation;
|
||||
var shortcutPath = $"{shortcutFolder}\\{ShortcutName}";
|
||||
if (File.Exists(shortcutPath))
|
||||
{
|
||||
@@ -73,7 +80,7 @@ namespace Daybreak.Services.Shortcuts
|
||||
return;
|
||||
}
|
||||
|
||||
var shortcutFolder = this.configurationManager.GetConfiguration().ShortcutLocation;
|
||||
var shortcutFolder = this.liveOptions.Value.ShortcutLocation;
|
||||
var shortcutPath = $"{shortcutFolder}\\{ShortcutName}";
|
||||
var currentExecutable = Process.GetCurrentProcess()?.MainModule?.FileName;
|
||||
var shortcut = Shortcut.CreateShortcut(currentExecutable);
|
||||
@@ -92,7 +99,7 @@ namespace Daybreak.Services.Shortcuts
|
||||
return;
|
||||
}
|
||||
|
||||
var shortcutFolder = this.configurationManager.GetConfiguration().ShortcutLocation;
|
||||
var shortcutFolder = this.liveOptions.Value.ShortcutLocation;
|
||||
var shortcutPath = $"{shortcutFolder}\\{ShortcutName}";
|
||||
File.Delete(shortcutPath);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.Runtime;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Models.Github;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.Http;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@@ -16,13 +20,14 @@ using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Extensions;
|
||||
using Version = Daybreak.Models.Versioning.Version;
|
||||
|
||||
namespace Daybreak.Services.Updater
|
||||
{
|
||||
public sealed class ApplicationUpdater : IApplicationUpdater
|
||||
{
|
||||
private const string LaunchActionName = "Launch_Daybreak";
|
||||
private const string UpdateDesiredKey = "UpdateDesired";
|
||||
private const string ExecutionPolicyKey = "ExecutionPolicy";
|
||||
private const string UpdatedKey = "Updating";
|
||||
private const string RegistryKey = "Daybreak";
|
||||
@@ -35,8 +40,10 @@ namespace Daybreak.Services.Updater
|
||||
private const string ProcessIdTag = "{PROCESSID}";
|
||||
private const string ExecutableNameTag = "{EXECUTABLE}";
|
||||
private const string WorkingDirectoryTag = "{WORKINGDIRECTORY}";
|
||||
private const string RefTagPrefix = "/refs/tags";
|
||||
private const string VersionListUrl = "https://api.github.com/repos/AlexMacocian/Daybreak/git/refs/tags";
|
||||
private const string Url = "https://github.com/AlexMacocian/Daybreak/releases/latest";
|
||||
private const string DownloadUrl = $"https://github.com/AlexMacocian/Daybreak/releases/download/v{VersionTag}/Daybreakv{VersionTag}.zip";
|
||||
private const string DownloadUrl = $"https://github.com/AlexMacocian/Daybreak/releases/download/{VersionTag}/Daybreak{VersionTag}.zip";
|
||||
private const string GetExecutionPolicyCommand = "Get-ExecutionPolicy -Scope CurrentUser";
|
||||
private const string SetExecutionPolicyCommand = $"Set-ExecutionPolicy {ExecutionPolicyTag} -Scope CurrentUser";
|
||||
private const string WaitCommand = $"Wait-Process -Id {ProcessIdTag}";
|
||||
@@ -51,46 +58,55 @@ namespace Daybreak.Services.Updater
|
||||
private const string RemovePs1 = $"Remove-item {ExtractAndRunPs1}";
|
||||
|
||||
private readonly CancellationTokenSource updateCancellationTokenSource = new();
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<ApplicationUpdater> logger;
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IRuntimeStore runtimeStore;
|
||||
private readonly HttpClient httpClient = new();
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly IHttpClient<ApplicationUpdater> httpClient;
|
||||
|
||||
public string CurrentVersion => Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
public Version CurrentVersion { get; }
|
||||
|
||||
public ApplicationUpdater(
|
||||
ILogger logger,
|
||||
IRuntimeStore runtimeStore,
|
||||
IViewManager viewManager)
|
||||
ILogger<ApplicationUpdater> logger,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
IViewManager viewManager,
|
||||
IHttpClient<ApplicationUpdater> httpClient)
|
||||
{
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.runtimeStore = runtimeStore.ThrowIfNull(nameof(runtimeStore));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.httpClient = httpClient.ThrowIfNull(nameof(httpClient));
|
||||
this.httpClient.DefaultRequestHeaders.Add("user-agent", "Daybreak Client");
|
||||
if (Version.TryParse(Assembly.GetExecutingAssembly().GetName().Version.ToString(), out var currentVersion))
|
||||
{
|
||||
if (currentVersion.HasPrefix is false)
|
||||
{
|
||||
currentVersion = Version.Parse("v" + currentVersion);
|
||||
}
|
||||
|
||||
this.CurrentVersion = currentVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FatalException($"Application version is invalid: {Assembly.GetExecutingAssembly().GetName().Version}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> DownloadUpdate(UpdateStatus updateStatus)
|
||||
public async Task<bool> DownloadUpdate(Version version, UpdateStatus updateStatus)
|
||||
{
|
||||
updateStatus.CurrentStep = UpdateStatus.CheckingLatestVersion;
|
||||
var latestVersion = (await this.GetLatestVersion()).ExtractValue();
|
||||
if (latestVersion is null)
|
||||
updateStatus.CurrentStep = UpdateStatus.InitializingDownload;
|
||||
var uri = DownloadUrl.Replace(VersionTag, version.ToString());
|
||||
using var response = await this.httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
|
||||
if (response.IsSuccessStatusCode is false)
|
||||
{
|
||||
this.logger.LogWarning("Failed to retrieve latest version. Aborting update");
|
||||
return false;
|
||||
}
|
||||
|
||||
using var downloadLatestResponse = await this.httpClient.GetAsync(
|
||||
DownloadUrl.Replace(VersionTag, latestVersion));
|
||||
|
||||
if (downloadLatestResponse.IsSuccessStatusCode is false)
|
||||
{
|
||||
this.logger.LogWarning("Failed to download latest version. Aborting udpate");
|
||||
updateStatus.CurrentStep = UpdateStatus.FailedDownload;
|
||||
this.logger.LogError($"Failed to download update. Details: {await response.Content.ReadAsStringAsync()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
using var downloadStream = await this.httpClient.GetStreamAsync(uri);
|
||||
this.logger.LogInformation("Beginning update download");
|
||||
var downloadStream = await downloadLatestResponse.Content.ReadAsStreamAsync();
|
||||
var fileStream = File.OpenWrite(TempFile);
|
||||
var downloadSize = (double)downloadStream.Length;
|
||||
var downloadSize = (double)response.Content.Headers.ContentLength;
|
||||
var buffer = new byte[1024];
|
||||
var length = 0;
|
||||
double downloaded = 0;
|
||||
@@ -113,12 +129,29 @@ namespace Daybreak.Services.Updater
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> DownloadLatestUpdate(UpdateStatus updateStatus)
|
||||
{
|
||||
updateStatus.CurrentStep = UpdateStatus.CheckingLatestVersion;
|
||||
var latestVersion = (await this.GetLatestVersion()).ExtractValue();
|
||||
if (latestVersion is null)
|
||||
{
|
||||
this.logger.LogWarning("Failed to retrieve latest version. Aborting update");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Version.TryParse(latestVersion, out var parsedVersion) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not parse retrieved version: {latestVersion}");
|
||||
}
|
||||
|
||||
return await this.DownloadUpdate(parsedVersion, updateStatus);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAvailable()
|
||||
{
|
||||
var version = string.Join('.', this.CurrentVersion.Split('.'));
|
||||
var maybeLatestVersion = await this.GetLatestVersion();
|
||||
return maybeLatestVersion.Switch(
|
||||
onSome: latestVersion => string.Compare(version, latestVersion, true) < 0,
|
||||
onSome: latestVersion => string.Compare(this.CurrentVersion.ToString().Trim('v'), latestVersion, true) < 0,
|
||||
onNone: () =>
|
||||
{
|
||||
this.logger.LogWarning("Failed to retrieve latest version");
|
||||
@@ -126,11 +159,25 @@ namespace Daybreak.Services.Updater
|
||||
}).ExtractValue();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Version>> GetVersions()
|
||||
{
|
||||
this.logger.LogInformation($"Retrieving version list from {VersionListUrl}");
|
||||
var response = await this.httpClient.GetAsync(VersionListUrl);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var serializedList = await response.Content.ReadAsStringAsync();
|
||||
var versionList = serializedList.Deserialize<GithubRefTag[]>();
|
||||
return versionList.Select(v => v.Ref.Remove(0, RefTagPrefix.Length)).Select(v => new Version(v));
|
||||
}
|
||||
|
||||
return new List<Version>();
|
||||
}
|
||||
|
||||
public void PeriodicallyCheckForUpdates()
|
||||
{
|
||||
System.Extensions.TaskExtensions.RunPeriodicAsync(async () =>
|
||||
{
|
||||
if (this.runtimeStore.TryGetValue<bool>(UpdateDesiredKey, out var desiringUpdate) && desiringUpdate is false)
|
||||
if (this.liveOptions.Value.AutoCheckUpdate is false)
|
||||
{
|
||||
this.updateCancellationTokenSource.Cancel();
|
||||
return;
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ApplicationLifetime;
|
||||
using Daybreak.Models.Versioning;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Extensions.Services;
|
||||
|
||||
namespace Daybreak.Services.Updater
|
||||
{
|
||||
public interface IApplicationUpdater : IApplicationLifetimeService
|
||||
{
|
||||
string CurrentVersion { get; }
|
||||
Version CurrentVersion { get; }
|
||||
void FinalizeUpdate();
|
||||
void PeriodicallyCheckForUpdates();
|
||||
Task<IEnumerable<Version>> GetVersions();
|
||||
Task<bool> UpdateAvailable();
|
||||
Task<bool> DownloadUpdate(UpdateStatus updateStatus);
|
||||
Task<bool> DownloadUpdate(Version version, UpdateStatus updateStatus);
|
||||
Task<bool> DownloadLatestUpdate(UpdateStatus updateStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Utils
|
||||
{
|
||||
public static class LoggingExtensions
|
||||
{
|
||||
public static void LogInformation(this ILogger logger, string message)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Information, message);
|
||||
}
|
||||
|
||||
public static void LogError(this ILogger logger, string message)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Error, message);
|
||||
}
|
||||
|
||||
public static void LogCritical(this ILogger logger, string message)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Critical, message);
|
||||
}
|
||||
|
||||
public static void LogWarning(this ILogger logger, string message)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Warning, message);
|
||||
}
|
||||
|
||||
public static void LogInformation(this ILogger logger, Exception e)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Information, e);
|
||||
}
|
||||
|
||||
public static void LogWarning(this ILogger logger, Exception e)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Warning, e);
|
||||
}
|
||||
|
||||
public static void LogError(this ILogger logger, Exception e)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Error, e);
|
||||
}
|
||||
|
||||
public static void LogCritical(this ILogger logger, Exception e)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
logger.Log(LogLevel.Critical, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Privilege;
|
||||
using Daybreak.Services.Runtime;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Views
|
||||
{
|
||||
@@ -14,23 +16,24 @@ namespace Daybreak.Views
|
||||
/// </summary>
|
||||
public partial class AskUpdateView : UserControl
|
||||
{
|
||||
private const string UpdateDesiredKey = "UpdateDesired";
|
||||
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<AskUpdateView> logger;
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IRuntimeStore runtimeStore;
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly IPrivilegeManager privilegeManager;
|
||||
private readonly IApplicationUpdater applicationUpdater;
|
||||
|
||||
public AskUpdateView(
|
||||
ILogger logger,
|
||||
ILogger<AskUpdateView> logger,
|
||||
IViewManager viewManager,
|
||||
IRuntimeStore runtimeStore,
|
||||
IPrivilegeManager privilegeManager)
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveOptions,
|
||||
IPrivilegeManager privilegeManager,
|
||||
IApplicationUpdater applicationUpdater)
|
||||
{
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.runtimeStore = runtimeStore.ThrowIfNull(nameof(runtimeStore));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.privilegeManager = privilegeManager.ThrowIfNull(nameof(privilegeManager));
|
||||
this.applicationUpdater = applicationUpdater.ThrowIfNull(nameof(applicationUpdater));
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
@@ -48,20 +51,21 @@ namespace Daybreak.Views
|
||||
private void NoButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
this.logger.LogInformation("User declined update");
|
||||
this.runtimeStore.StoreValue(UpdateDesiredKey, false);
|
||||
this.liveOptions.Value.AutoCheckUpdate = false;
|
||||
this.liveOptions.UpdateOption();
|
||||
this.viewManager.ShowView<MainView>();
|
||||
}
|
||||
|
||||
private void YesButton_Clicked(object sender, System.EventArgs e)
|
||||
private async void YesButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
this.logger.LogInformation("User accepted update");
|
||||
this.runtimeStore.StoreValue(UpdateDesiredKey, true);
|
||||
if (this.CheckIfAdmin() is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.viewManager.ShowView<UpdateView>();
|
||||
var latestVersion = (await this.applicationUpdater.GetVersions()).Last();
|
||||
this.viewManager.ShowView<UpdateView>(latestVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
@@ -35,7 +36,17 @@
|
||||
<controls:SaveButton Foreground="White" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5"
|
||||
Clicked="SaveButton_Clicked" Grid.Column="2" IsEnabled="{Binding ElementName=_this, Path=SaveButtonEnabled, Mode=OneWay}"></controls:SaveButton>
|
||||
</Grid>
|
||||
<controls:BuildTemplate Grid.Row="1" DataContext="{Binding ElementName=_this, Path=CurrentBuild, Mode=OneWay}">
|
||||
<Grid Grid.Row="1" Margin="10, 0, 10, 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Code: " Foreground="White" Background="Transparent" FontSize="16"></TextBlock>
|
||||
<TextBox Grid.Column="1" Foreground="White" Background="Transparent" FontSize="16"
|
||||
Text="{Binding ElementName=_this, Path=CurrentBuildCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
|
||||
</Grid>
|
||||
<controls:BuildTemplate x:Name="BuildTemplate" Grid.Row="2" DataContext="{Binding ElementName=_this, Path=CurrentBuild, Mode=OneWay}"
|
||||
BuildChanged="BuildTemplate_BuildChanged">
|
||||
</controls:BuildTemplate>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Views
|
||||
{
|
||||
@@ -17,47 +23,89 @@ namespace Daybreak.Views
|
||||
{
|
||||
private const string DisallowedChars = "\r\n\\/.";
|
||||
|
||||
public readonly static DependencyProperty CurrentBuildProperty =
|
||||
DependencyPropertyExtensions.Register<BuildTemplateView, BuildEntry>(nameof(CurrentBuild));
|
||||
public readonly static DependencyProperty SaveButtonEnabledProperty =
|
||||
DependencyPropertyExtensions.Register<BuildTemplateView, bool>(nameof(SaveButtonEnabled), new PropertyMetadata(false));
|
||||
private bool supressDecode = false;
|
||||
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
private readonly ILogger<BuildTemplateView> logger;
|
||||
|
||||
public bool SaveButtonEnabled
|
||||
{
|
||||
get => this.GetTypedValue<bool>(SaveButtonEnabledProperty);
|
||||
set => this.SetValue(SaveButtonEnabledProperty, value);
|
||||
}
|
||||
|
||||
public BuildEntry CurrentBuild
|
||||
{
|
||||
get => this.GetTypedValue<BuildEntry>(CurrentBuildProperty);
|
||||
set => this.SetValue(CurrentBuildProperty, value);
|
||||
}
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool saveButtonEnabled;
|
||||
[GenerateDependencyProperty]
|
||||
private BuildEntry currentBuild;
|
||||
[GenerateDependencyProperty]
|
||||
private string currentBuildCode;
|
||||
|
||||
public BuildTemplateView(
|
||||
IViewManager viewManager,
|
||||
IBuildTemplateManager buildTemplateManager)
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
IIconRetriever iconRetriever,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
ILogger<ChromiumBrowserWrapper> chromiumLogger,
|
||||
ILogger<BuildTemplateView> logger)
|
||||
{
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull(nameof(buildTemplateManager));
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.InitializeComponent();
|
||||
this.BuildTemplate.InitializeTemplate(iconRetriever, liveOptions, buildTemplateManager, chromiumLogger);
|
||||
this.DataContextChanged += (sender, contextArgs) =>
|
||||
{
|
||||
if (contextArgs.NewValue is BuildEntry)
|
||||
{
|
||||
this.logger.LogInformation("Received data context. Setting current build");
|
||||
this.CurrentBuild = contextArgs.NewValue.As<BuildEntry>();
|
||||
this.CurrentBuildCode = this.buildTemplateManager.EncodeTemplate(this.CurrentBuild.Build);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == CurrentBuildCodeProperty && this.supressDecode is false)
|
||||
{
|
||||
this.logger.LogInformation($"Attempting to decode provided template {this.CurrentBuildCode}");
|
||||
try
|
||||
{
|
||||
this.CurrentBuild = new BuildEntry
|
||||
{
|
||||
Name = this.CurrentBuild.Name,
|
||||
PreviousName = this.CurrentBuild.PreviousName,
|
||||
Build = this.buildTemplateManager.DecodeTemplate(this.CurrentBuildCode)
|
||||
};
|
||||
|
||||
this.logger.LogInformation($"Template {CurrentBuildCode} decoded");
|
||||
}
|
||||
catch
|
||||
{
|
||||
this.logger.LogWarning($"Failed to decode {this.CurrentBuildCode}. Reverting to default build");
|
||||
this.CurrentBuild = new BuildEntry
|
||||
{
|
||||
Name = this.CurrentBuild.Name,
|
||||
PreviousName = this.CurrentBuild.PreviousName,
|
||||
Build = new Build()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildTemplate_BuildChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.supressDecode = true;
|
||||
this.CurrentBuildCode = this.buildTemplateManager.EncodeTemplate(this.CurrentBuild.Build);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.supressDecode = false;
|
||||
}
|
||||
}
|
||||
private void BackButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<BuildsListView>();
|
||||
}
|
||||
|
||||
private void SaveButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.buildTemplateManager.SaveBuild(this.CurrentBuild);
|
||||
@@ -71,7 +119,6 @@ namespace Daybreak.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sender.As<TextBox>().Text))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
@@ -9,6 +10,7 @@ using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Views
|
||||
{
|
||||
@@ -17,15 +19,15 @@ namespace Daybreak.Views
|
||||
/// </summary>
|
||||
public partial class ExecutablesView : UserControl
|
||||
{
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions;
|
||||
private readonly IViewManager viewManager;
|
||||
public ObservableCollection<GuildwarsPath> Paths { get; } = new();
|
||||
|
||||
public ExecutablesView(
|
||||
IConfigurationManager configurationManager,
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions,
|
||||
IViewManager viewManager)
|
||||
{
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveUpdateableOptions = liveUpdateableOptions.ThrowIfNull(nameof(liveUpdateableOptions));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.InitializeComponent();
|
||||
this.GetPaths();
|
||||
@@ -33,7 +35,7 @@ namespace Daybreak.Views
|
||||
|
||||
private void GetPaths()
|
||||
{
|
||||
this.Paths.AddRange(this.configurationManager.GetConfiguration().GuildwarsPaths);
|
||||
this.Paths.AddRange(this.liveUpdateableOptions.Value.GuildwarsPaths);
|
||||
}
|
||||
|
||||
private void BackButton_Clicked(object sender, EventArgs e)
|
||||
@@ -53,9 +55,8 @@ namespace Daybreak.Views
|
||||
|
||||
private void SaveButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
config.GuildwarsPaths = this.Paths.ToList();
|
||||
this.configurationManager.SaveConfiguration(config);
|
||||
this.liveUpdateableOptions.Value.GuildwarsPaths = this.Paths.ToList();
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.viewManager.ShowView<SettingsCategoryView>();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
@@ -27,7 +28,7 @@ namespace Daybreak.Views
|
||||
DependencyPropertyExtensions.Register<ExperimentalSettingsView, bool>(nameof(MacrosEnabled));
|
||||
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions;
|
||||
|
||||
public bool LaunchAsCurrentUser
|
||||
{
|
||||
@@ -57,17 +58,17 @@ namespace Daybreak.Views
|
||||
|
||||
public ExperimentalSettingsView(
|
||||
IViewManager viewManager,
|
||||
IConfigurationManager configurationManager)
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions)
|
||||
{
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveUpdateableOptions = liveUpdateableOptions.ThrowIfNull(nameof(liveUpdateableOptions));
|
||||
this.InitializeComponent();
|
||||
this.LoadExperimentalSettings();
|
||||
}
|
||||
|
||||
private void LoadExperimentalSettings()
|
||||
{
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
var config = this.liveUpdateableOptions.Value;
|
||||
this.MultiLaunch = config.ExperimentalFeatures.MultiLaunchSupport;
|
||||
this.GWToolboxLaunchDelay = config.ExperimentalFeatures.ToolboxAutoLaunchDelay.ToString();
|
||||
this.DynamicBuildLoading = config.ExperimentalFeatures.DynamicBuildLoading;
|
||||
@@ -77,7 +78,7 @@ namespace Daybreak.Views
|
||||
|
||||
private void SaveExperimentalSettings()
|
||||
{
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
var config = this.liveUpdateableOptions.Value;
|
||||
config.ExperimentalFeatures.MultiLaunchSupport = this.MultiLaunch;
|
||||
config.ExperimentalFeatures.DynamicBuildLoading = this.DynamicBuildLoading;
|
||||
config.ExperimentalFeatures.LaunchGuildwarsAsCurrentUser = this.LaunchAsCurrentUser;
|
||||
@@ -87,7 +88,7 @@ namespace Daybreak.Views
|
||||
config.ExperimentalFeatures.ToolboxAutoLaunchDelay = gwToolboxLaunchDelay;
|
||||
}
|
||||
|
||||
this.configurationManager.SaveConfiguration(config);
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
}
|
||||
|
||||
private void SaveButton_Clicked(object sender, EventArgs e)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<UserControl x:Class="Daybreak.Views.LogsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Views"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<Style TargetType="{x:Type TextBlock}" x:Key="WrapText">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="#A0202020">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<controls:BackButton Foreground="White" Height="30" Width="30" HorizontalAlignment="Left" Margin="5"
|
||||
Clicked="BackButton_Clicked"></controls:BackButton>
|
||||
<controls:BinButton Foreground="White" Height="30" Width="30" HorizontalAlignment="Right" Margin="5"
|
||||
Clicked="BinButton_Clicked"></controls:BinButton>
|
||||
<controls:RefreshGlyph Foreground="White" Height="30" Width="30" HorizontalAlignment="Right" Margin="0, 5, 45, 5"
|
||||
Clicked="RefreshGlyph_Clicked"></controls:RefreshGlyph>
|
||||
<controls:BackButton Foreground="White" Height="30" Width="30" HorizontalAlignment="Right" Margin="0, 5, 85, 5"
|
||||
Clicked="ExportButton_Clicked">
|
||||
<controls:BackButton.RenderTransform>
|
||||
<RotateTransform Angle="270" CenterX="15" CenterY="15"></RotateTransform>
|
||||
</controls:BackButton.RenderTransform>
|
||||
</controls:BackButton>
|
||||
<DataGrid IsReadOnly="True" Background="Transparent" Foreground="White" Grid.Row="1"
|
||||
ItemsSource="{Binding ElementName=_this, Path=Logs, Mode=OneWay}" HorizontalScrollBarVisibility="Disabled"
|
||||
AutoGenerateColumns="False" HeadersVisibility="Column" EnableColumnVirtualization="True"
|
||||
EnableRowVirtualization="True">
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style TargetType="{x:Type DataGridColumnHeader}">
|
||||
<Setter Property="Foreground" Value="White"></Setter>
|
||||
<Setter Property="Background" Value="Transparent"></Setter>
|
||||
<Setter Property="BorderBrush" Value="#80808080"></Setter>
|
||||
<Setter Property="BorderThickness" Value="1"></Setter>
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
<DataGrid.CellStyle>
|
||||
<Style TargetType="{x:Type DataGridCell}">
|
||||
<Setter Property="BorderBrush" Value="#80808080"></Setter>
|
||||
<Setter Property="BorderThickness" Value="1"></Setter>
|
||||
</Style>
|
||||
</DataGrid.CellStyle>
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="{x:Type DataGridRow}">
|
||||
<Setter Property="Background" Value="Transparent"></Setter>
|
||||
<Setter Property="Foreground" Value="White"></Setter>
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn IsReadOnly="True" Header="DateTime" Binding="{Binding LogTime}" ElementStyle="{StaticResource WrapText}" Width="auto"/>
|
||||
<DataGridTextColumn IsReadOnly="True" Header="CV" Binding="{Binding CorrelationVector}" ElementStyle="{StaticResource WrapText}" Width="auto"/>
|
||||
<DataGridTextColumn IsReadOnly="True" Header="Category" Binding="{Binding Category}" ElementStyle="{StaticResource WrapText}" Width="auto"/>
|
||||
<DataGridTextColumn IsReadOnly="True" Header="LogLevel" Binding="{Binding LogLevel}" ElementStyle="{StaticResource WrapText}" Width="auto"/>
|
||||
<DataGridTextColumn IsReadOnly="True" Header="EventId" Binding="{Binding EventId}" ElementStyle="{StaticResource WrapText}" Width="auto"/>
|
||||
<DataGridTemplateColumn IsReadOnly="True" Header="Message" Width="*">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<controls:LogMessageTemplate Message="{Binding Message}" Foreground="White"></controls:LogMessageTemplate>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,79 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Extensions;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for LogsView.xaml
|
||||
/// </summary>
|
||||
public partial class LogsView : UserControl
|
||||
{
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly ILogsManager logManager;
|
||||
private readonly ILogger<LogsView> logger;
|
||||
|
||||
public ObservableCollection<Log> Logs { get; } = new ObservableCollection<Log>();
|
||||
|
||||
public LogsView(
|
||||
IViewManager viewManager,
|
||||
ILogsManager logManager,
|
||||
ILogger<LogsView> logger)
|
||||
{
|
||||
this.logManager = logManager.ThrowIfNull(nameof(logManager));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||
this.InitializeComponent();
|
||||
this.UpdateLogs();
|
||||
}
|
||||
|
||||
private void UpdateLogs()
|
||||
{
|
||||
this.Logs.ClearAnd().AddRange(this.logManager.GetLogs(l => l.LogLevel < Microsoft.Extensions.Logging.LogLevel.Trace));
|
||||
}
|
||||
private async void ExportButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.logger.LogInformation("Exporting logs");
|
||||
var saveFileDialog = new SaveFileDialog
|
||||
{
|
||||
DefaultExt = "json",
|
||||
Filter = "Json files (*.json)|*.json",
|
||||
Title = "Export logs",
|
||||
ValidateNames = true,
|
||||
CreatePrompt = true
|
||||
};
|
||||
if (saveFileDialog.ShowDialog() is true)
|
||||
{
|
||||
var fileName = saveFileDialog.FileName;
|
||||
this.logger.LogInformation($"Exporting to {fileName}");
|
||||
await File.WriteAllTextAsync(fileName, this.logManager.GetLogs().ToList().Serialize());
|
||||
}
|
||||
else
|
||||
{
|
||||
this.logger.LogInformation("Exporting canceled");
|
||||
}
|
||||
}
|
||||
private void BackButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<SettingsCategoryView>();
|
||||
}
|
||||
private void BinButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.logManager.DeleteLogs();
|
||||
this.UpdateLogs();
|
||||
}
|
||||
private void RefreshGlyph_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.UpdateLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,8 @@
|
||||
Clicked="LaunchTexmodButton_Clicked" Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="1"
|
||||
Visibility="{Binding ElementName=_this, Path=ButtonsVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"></controls:OpaqueButton>
|
||||
<Grid Grid.Column="2" Margin="10" Visibility="{Binding ElementName=_this, Path=BrowsersEnabled, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}">
|
||||
<controls:ChromiumBrowserWrapper Address="{Binding ElementName=_this, Path=RightBrowserAddress, Mode=OneWay}"
|
||||
<controls:ChromiumBrowserWrapper x:Name="RightWebBrowser"
|
||||
Address="{Binding ElementName=_this, Path=RightBrowserAddress, Mode=OneWay}"
|
||||
Foreground="White" FavoriteUriChanged="RightBrowser_FavoriteUriChanged"
|
||||
FavoriteAddress="{Binding ElementName=_this, Path=RightBrowserFavoriteAddress, Mode=OneWay}"
|
||||
MaximizeClicked="RightChromiumBrowserWrapper_MaximizeClicked"
|
||||
@@ -48,7 +49,8 @@
|
||||
CanDownloadBuild="True"/>
|
||||
</Grid>
|
||||
<Grid Grid.Column="0" Margin="10" Visibility="{Binding ElementName=_this, Path=BrowsersEnabled, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}">
|
||||
<controls:ChromiumBrowserWrapper Address="{Binding ElementName=_this, Path=LeftBrowserAddress, Mode=OneWay}"
|
||||
<controls:ChromiumBrowserWrapper x:Name="LeftWebBrowser"
|
||||
Address="{Binding ElementName=_this, Path=LeftBrowserAddress, Mode=OneWay}"
|
||||
Foreground="White" FavoriteUriChanged="LeftBrowser_FavoriteUriChanged"
|
||||
FavoriteAddress="{Binding ElementName=_this, Path=LeftBrowserFavoriteAddress, Mode=OneWay}"
|
||||
MaximizeClicked="LeftChromiumBrowserWrapper_MaximizeClicked"
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Controls;
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Screens;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
@@ -24,8 +28,10 @@ namespace Daybreak.Views
|
||||
{
|
||||
private readonly IApplicationLauncher applicationDetector;
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly IScreenManager screenManager;
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
private readonly ILogger<ChromiumBrowserWrapper> browserLogger;
|
||||
private readonly CancellationTokenSource cancellationTokenSource = new();
|
||||
|
||||
private bool leftBrowserMaximized = false;
|
||||
@@ -53,21 +59,32 @@ namespace Daybreak.Views
|
||||
public MainView(
|
||||
IApplicationLauncher applicationDetector,
|
||||
IViewManager viewManager,
|
||||
IConfigurationManager configurationManager,
|
||||
IScreenManager screenManager)
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveOptions,
|
||||
IScreenManager screenManager,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> browserLogger)
|
||||
{
|
||||
this.browserLogger = browserLogger;
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull(nameof(buildTemplateManager));
|
||||
this.screenManager = screenManager.ThrowIfNull(nameof(screenManager));
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.applicationDetector = applicationDetector.ThrowIfNull(nameof(applicationDetector));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.InitializeComponent();
|
||||
this.PeriodicallyCheckGameState();
|
||||
this.InitializeBrowsers();
|
||||
this.NavigateToDefaults();
|
||||
}
|
||||
|
||||
private void InitializeBrowsers()
|
||||
{
|
||||
this.LeftWebBrowser.InitializeBrowser(this.liveOptions, this.buildTemplateManager, this.browserLogger);
|
||||
this.RightWebBrowser.InitializeBrowser(this.liveOptions, this.buildTemplateManager, this.browserLogger);
|
||||
}
|
||||
|
||||
private void NavigateToDefaults()
|
||||
{
|
||||
var applicationConfiguration = this.configurationManager.GetConfiguration();
|
||||
var applicationConfiguration = this.liveOptions.Value;
|
||||
if (applicationConfiguration.BrowsersEnabled)
|
||||
{
|
||||
this.LeftBrowserFavoriteAddress = applicationConfiguration.LeftBrowserDefault;
|
||||
@@ -111,9 +128,9 @@ namespace Daybreak.Views
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.configurationManager.GetConfiguration().SetGuildwarsWindowSizeOnLaunch)
|
||||
if (this.liveOptions.Value.SetGuildwarsWindowSizeOnLaunch)
|
||||
{
|
||||
var id = this.configurationManager.GetConfiguration().DesiredGuildwarsScreen;
|
||||
var id = this.liveOptions.Value.DesiredGuildwarsScreen;
|
||||
var desiredScreen = this.screenManager.Screens.Skip(id).FirstOrDefault();
|
||||
if (desiredScreen is null)
|
||||
{
|
||||
@@ -123,9 +140,9 @@ namespace Daybreak.Views
|
||||
this.screenManager.MoveGuildwarsToScreen(desiredScreen);
|
||||
}
|
||||
|
||||
if (this.configurationManager.GetConfiguration().ToolboxAutoLaunch is true)
|
||||
if (this.liveOptions.Value.ToolboxAutoLaunch is true)
|
||||
{
|
||||
var delay = this.configurationManager.GetConfiguration().ExperimentalFeatures.ToolboxAutoLaunchDelay;
|
||||
var delay = this.liveOptions.Value.ExperimentalFeatures.ToolboxAutoLaunchDelay;
|
||||
await Task.Delay(delay);
|
||||
await this.applicationDetector.LaunchGuildwarsToolbox();
|
||||
}
|
||||
@@ -164,23 +181,23 @@ namespace Daybreak.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void ChromiumBrowserWrapper_BuildDecoded(object sender, Models.Builds.Build e)
|
||||
private void ChromiumBrowserWrapper_BuildDecoded(object sender, Build e)
|
||||
{
|
||||
this.viewManager.ShowView<BuildTemplateView>(new BuildEntry { Build = e, Name = string.Empty });
|
||||
}
|
||||
|
||||
private void LeftBrowser_FavoriteUriChanged(object sender, string e)
|
||||
{
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
var config = this.liveOptions.Value;
|
||||
config.LeftBrowserDefault = e;
|
||||
this.configurationManager.SaveConfiguration(config);
|
||||
this.liveOptions.UpdateOption();
|
||||
}
|
||||
|
||||
private void RightBrowser_FavoriteUriChanged(object sender, string e)
|
||||
{
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
var config = this.liveOptions.Value;
|
||||
config.RightBrowserDefault = e;
|
||||
this.configurationManager.SaveConfiguration(config);
|
||||
this.liveOptions.UpdateOption();
|
||||
}
|
||||
|
||||
private void LeftChromiumBrowserWrapper_MaximizeClicked(object sender, EventArgs e)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
using System.Windows.Controls;
|
||||
|
||||
@@ -15,12 +14,12 @@ namespace Daybreak.Views
|
||||
{
|
||||
private readonly IApplicationLauncher applicationLauncher;
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<RequestElevationView> logger;
|
||||
|
||||
public RequestElevationView(
|
||||
IApplicationLauncher applicationLauncher,
|
||||
IViewManager viewManager,
|
||||
ILogger logger)
|
||||
ILogger<RequestElevationView> logger)
|
||||
{
|
||||
this.applicationLauncher = applicationLauncher.ThrowIfNull(nameof(applicationLauncher));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Daybreak.Controls.Templates;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Controls.Templates;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.Configuration;
|
||||
@@ -23,7 +24,7 @@ namespace Daybreak.Views
|
||||
{
|
||||
private readonly IScreenManager screenManager;
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly IApplicationLauncher applicationLauncher;
|
||||
private int selectedId;
|
||||
|
||||
@@ -33,15 +34,15 @@ namespace Daybreak.Views
|
||||
public ScreenChoiceView(
|
||||
IViewManager viewManager,
|
||||
IScreenManager screenManager,
|
||||
IConfigurationManager configurationManager,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
IApplicationLauncher applicationLauncher)
|
||||
{
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.screenManager = screenManager.ThrowIfNull(nameof(screenManager));
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveOptions = liveOptions.ThrowIfNull(nameof(liveOptions));
|
||||
this.applicationLauncher = applicationLauncher.ThrowIfNull(nameof(applicationLauncher));
|
||||
this.InitializeComponent();
|
||||
this.selectedId = configurationManager.GetConfiguration().DesiredGuildwarsScreen;
|
||||
this.selectedId = this.liveOptions.Value.DesiredGuildwarsScreen;
|
||||
this.CanTest = applicationLauncher.IsGuildwarsRunning;
|
||||
this.SetupView();
|
||||
}
|
||||
@@ -86,7 +87,7 @@ namespace Daybreak.Views
|
||||
|
||||
private void SaveButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.configurationManager.GetConfiguration().DesiredGuildwarsScreen = this.selectedId;
|
||||
this.liveOptions.Value.DesiredGuildwarsScreen = this.selectedId;
|
||||
this.viewManager.ShowView<SettingsCategoryView>();
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,18 @@
|
||||
<controls:FireballGlyph></controls:FireballGlyph>
|
||||
</controls:TileButton.InnerContent>
|
||||
</controls:TileButton>
|
||||
<controls:TileButton Title="Version management" Foreground="White" BorderBrush="White" BorderThickness="2"
|
||||
HighlightColor="White" Clicked="VersionButton_Clicked" Height="150" Width="150">
|
||||
<controls:TileButton.InnerContent>
|
||||
<controls:StaticGlyph></controls:StaticGlyph>
|
||||
</controls:TileButton.InnerContent>
|
||||
</controls:TileButton>
|
||||
<controls:TileButton Title="Logs" Foreground="White" BorderBrush="White" BorderThickness="2"
|
||||
HighlightColor="White" Clicked="LogsButton_Clicked" Height="150" Width="150">
|
||||
<controls:TileButton.InnerContent>
|
||||
<controls:LogsGlyph></controls:LogsGlyph>
|
||||
</controls:TileButton.InnerContent>
|
||||
</controls:TileButton>
|
||||
</WrapPanel>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -38,6 +38,16 @@ namespace Daybreak.Views
|
||||
this.viewManager.ShowView<BuildsListView>();
|
||||
}
|
||||
|
||||
private void VersionButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<VersionManagementView>(this);
|
||||
}
|
||||
|
||||
private void LogsButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<LogsView>();
|
||||
}
|
||||
|
||||
private void FileButton_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<ExecutablesView>();
|
||||
|
||||
@@ -82,7 +82,8 @@
|
||||
<controls:SaveButton Foreground="White" Height="30" Width="30" Grid.Column="1" HorizontalAlignment="Right" Margin="5"
|
||||
Clicked="SaveButton_Clicked"></controls:SaveButton>
|
||||
<StackPanel Orientation="Vertical" Grid.Row="1">
|
||||
<TextBlock Text="Texmod path" FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Auto check for updates: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Texmod path: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="GWToolbox auto-launch: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="GWToolbox path: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Browsers enabled: " FontSize="22" Foreground="White" Height="30"/>
|
||||
@@ -91,10 +92,13 @@
|
||||
<TextBlock Text="Right browser homepage: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Auto-place on desired screen: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Desired screen id: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Place Shortcut" FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Shortcut folder" FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Place Shortcut: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Shortcut folder: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
<TextBlock Text="Keep local cache of icons: " FontSize="22" Foreground="White" Height="30"></TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="1">
|
||||
<ToggleButton HorizontalAlignment="Center" HorizontalContentAlignment="Stretch" Style="{StaticResource AnimatedSwitch}" Height="30" Width="40"
|
||||
FontSize="22" Foreground="White" IsChecked="{Binding ElementName=_this, Path=AutoCheckUpdate, Mode=TwoWay}"></ToggleButton>
|
||||
<Grid Height="30">
|
||||
<TextBox HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||
FontSize="22" Margin="0, 0, 30, 0" Background="Transparent" Foreground="White"
|
||||
@@ -145,6 +149,8 @@
|
||||
Foreground="White" BorderBrush="Gray" BorderThickness="0"
|
||||
Clicked="ShortcutFolderPickerGlyph_Clicked"></controls:FilePickerGlyph>
|
||||
</Grid>
|
||||
<ToggleButton HorizontalAlignment="Center" HorizontalContentAlignment="Stretch" Style="{StaticResource AnimatedSwitch}" Height="30" Width="40"
|
||||
FontSize="22" Foreground="White" IsChecked="{Binding ElementName=_this, Path=KeepLocalIconCache, Mode=TwoWay}"></ToggleButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Shortcuts;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Microsoft.Win32;
|
||||
@@ -18,7 +19,7 @@ namespace Daybreak.Views
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Used by source generators")]
|
||||
public partial class SettingsView : System.Windows.Controls.UserControl
|
||||
{
|
||||
private readonly IConfigurationManager configurationManager;
|
||||
private readonly ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions;
|
||||
private readonly IViewManager viewManager;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
@@ -43,13 +44,16 @@ namespace Daybreak.Views
|
||||
private string shortcutFolder;
|
||||
[GenerateDependencyProperty]
|
||||
private bool shortcutPlaced;
|
||||
[GenerateDependencyProperty]
|
||||
private bool autoCheckUpdate;
|
||||
[GenerateDependencyProperty]
|
||||
private bool keepLocalIconCache;
|
||||
|
||||
public SettingsView(
|
||||
IConfigurationManager configurationManager,
|
||||
IViewManager viewManager,
|
||||
IShortcutManager shortcutManager)
|
||||
ILiveUpdateableOptions<ApplicationConfiguration> liveUpdateableOptions,
|
||||
IViewManager viewManager)
|
||||
{
|
||||
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
|
||||
this.liveUpdateableOptions = liveUpdateableOptions.ThrowIfNull(nameof(liveUpdateableOptions));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.InitializeComponent();
|
||||
this.LoadSettings();
|
||||
@@ -57,7 +61,7 @@ namespace Daybreak.Views
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
var config = this.configurationManager.GetConfiguration();
|
||||
var config = this.liveUpdateableOptions.Value;
|
||||
this.AddressBarReadonly = config.AddressBarReadonly;
|
||||
this.ToolboxPath = config.ToolboxPath;
|
||||
this.LeftBrowserUrl = config.LeftBrowserDefault;
|
||||
@@ -69,12 +73,13 @@ namespace Daybreak.Views
|
||||
this.DesiredScreen = config.DesiredGuildwarsScreen.ToString();
|
||||
this.ShortcutFolder = config.ShortcutLocation;
|
||||
this.ShortcutPlaced = config.PlaceShortcut;
|
||||
|
||||
this.AutoCheckUpdate = config.AutoCheckUpdate;
|
||||
this.KeepLocalIconCache = config.KeepLocalIconCache;
|
||||
}
|
||||
|
||||
private void SaveButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var currentConfig = this.configurationManager.GetConfiguration();
|
||||
var currentConfig = this.liveUpdateableOptions.Value;
|
||||
currentConfig.ToolboxPath = this.ToolboxPath;
|
||||
currentConfig.AddressBarReadonly = this.AddressBarReadonly;
|
||||
currentConfig.LeftBrowserDefault = this.LeftBrowserUrl;
|
||||
@@ -86,7 +91,9 @@ namespace Daybreak.Views
|
||||
currentConfig.DesiredGuildwarsScreen = int.Parse(this.DesiredScreen);
|
||||
currentConfig.ShortcutLocation = this.ShortcutFolder;
|
||||
currentConfig.PlaceShortcut = this.ShortcutPlaced;
|
||||
this.configurationManager.SaveConfiguration(currentConfig);
|
||||
currentConfig.AutoCheckUpdate = this.AutoCheckUpdate;
|
||||
currentConfig.KeepLocalIconCache = this.KeepLocalIconCache;
|
||||
this.liveUpdateableOptions.UpdateOption();
|
||||
this.viewManager.ShowView<SettingsCategoryView>();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Services.Logging;
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using Version = Daybreak.Models.Versioning.Version;
|
||||
|
||||
namespace Daybreak.Views
|
||||
{
|
||||
@@ -16,7 +17,7 @@ namespace Daybreak.Views
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Used by source generators")]
|
||||
public partial class UpdateView : UserControl
|
||||
{
|
||||
private readonly ILogger logger;
|
||||
private readonly ILogger<UpdateView> logger;
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IApplicationUpdater applicationUpdater;
|
||||
private readonly UpdateStatus updateStatus = new();
|
||||
@@ -31,7 +32,7 @@ namespace Daybreak.Views
|
||||
|
||||
public UpdateView(
|
||||
IApplicationUpdater applicationUpdater,
|
||||
ILogger logger,
|
||||
ILogger<UpdateView> logger,
|
||||
IViewManager viewManager)
|
||||
{
|
||||
this.applicationUpdater = applicationUpdater;
|
||||
@@ -56,8 +57,14 @@ namespace Daybreak.Views
|
||||
|
||||
private async void UpdateView_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not Version version)
|
||||
{
|
||||
this.viewManager.ShowView<MainView>();
|
||||
throw new InvalidOperationException("No version specified for download");
|
||||
}
|
||||
|
||||
this.logger.LogInformation("Starting update procedure");
|
||||
var success = await applicationUpdater.DownloadUpdate(updateStatus).ConfigureAwait(true);
|
||||
var success = await applicationUpdater.DownloadUpdate(version, updateStatus).ConfigureAwait(true);
|
||||
if (success is false)
|
||||
{
|
||||
this.logger.LogError("Update procedure failed");
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<UserControl x:Class="Daybreak.Views.VersionManagementView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Views"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#A0202020">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<controls:BackButton Foreground="White" Height="30" Width="30" Grid.Column="0" HorizontalAlignment="Left" Margin="5"
|
||||
Clicked="BackButton_Clicked"></controls:BackButton>
|
||||
<TextBlock Text="Manage application version" FontSize="18" Foreground="White" HorizontalAlignment="Center"></TextBlock>
|
||||
<WrapPanel Grid.Row="1" HorizontalAlignment="Center" Margin="10">
|
||||
<TextBlock Text="Current version: " Foreground="White" FontSize="16"></TextBlock>
|
||||
<controls:OpaqueButton Text="{Binding ElementName=_this, Path=CurrentVersion.VersionString, Mode=OneWay}" Foreground="White" FontSize="16"
|
||||
Cursor="Hand" BorderBrush="Transparent" BorderThickness="0" Clicked="CurrentVersion_Clicked"></controls:OpaqueButton>
|
||||
</WrapPanel>
|
||||
<ListView Grid.Row="2"
|
||||
Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Versions, Mode=OneWay}"
|
||||
HorizontalContentAlignment="Stretch" Width="230" ScrollViewer.CanContentScroll="True"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Auto">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="5">
|
||||
<controls:OpaqueButton Text="{Binding VersionString}" Clicked="DesiredVersion_Clicked"
|
||||
Foreground="White" FontSize="16" BorderThickness="0"
|
||||
HorizontalAlignment="Left"></controls:OpaqueButton>
|
||||
<controls:BackButton Foreground="White" Width="30" Height="30" HorizontalAlignment="Right"
|
||||
Clicked="DesiredVersion_DownloadButton_Clicked">
|
||||
<controls:BackButton.RenderTransform>
|
||||
<RotateTransform Angle="270" CenterX="15" CenterY="15"></RotateTransform>
|
||||
</controls:BackButton.RenderTransform>
|
||||
</controls:BackButton>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,92 @@
|
||||
using Daybreak.Services.Updater;
|
||||
using Daybreak.Services.ViewManagement;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using Version = Daybreak.Models.Versioning.Version;
|
||||
|
||||
namespace Daybreak.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for VersionManagementView.xaml
|
||||
/// </summary>
|
||||
public partial class VersionManagementView : UserControl
|
||||
{
|
||||
private const string VersionPlaceholder = "{VERSION}";
|
||||
private const string ReleaseURL = $"https://github.com/AlexMacocian/Daybreak/releases/tag/{VersionPlaceholder}";
|
||||
|
||||
private readonly IApplicationUpdater applicationUpdater;
|
||||
private readonly IViewManager viewManager;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private Version currentVersion;
|
||||
|
||||
public ObservableCollection<Version> Versions { get; } = new();
|
||||
|
||||
public VersionManagementView(
|
||||
IApplicationUpdater applicationUpdater,
|
||||
IViewManager viewManager)
|
||||
{
|
||||
this.applicationUpdater = applicationUpdater.ThrowIfNull(nameof(applicationUpdater));
|
||||
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
|
||||
this.InitializeComponent();
|
||||
this.CurrentVersion = this.applicationUpdater.CurrentVersion;
|
||||
this.LoadVersionList();
|
||||
}
|
||||
|
||||
private async void LoadVersionList()
|
||||
{
|
||||
this.Versions.ClearAnd().AddRange(await this.applicationUpdater.GetVersions());
|
||||
}
|
||||
|
||||
private void CurrentVersion_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
Process.Start("explorer.exe", ReleaseURL.Replace(VersionPlaceholder, this.currentVersion.ToString()));
|
||||
}
|
||||
|
||||
private void DesiredVersion_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is not UserControl userControl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (userControl.DataContext is not Version desiredVersion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Process.Start("explorer.exe", ReleaseURL.Replace(VersionPlaceholder, desiredVersion.ToString()));
|
||||
}
|
||||
|
||||
private void DesiredVersion_DownloadButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is not UserControl userControl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (userControl.DataContext is not Version desiredVersion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.viewManager.ShowView<UpdateView>(desiredVersion);
|
||||
}
|
||||
|
||||
private void BackButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is UserControl userControl)
|
||||
{
|
||||
this.viewManager.ShowView(userControl.GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
this.viewManager.ShowView<MainView>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user