mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-19 23:05:03 +00:00
Compare commits
56
Commits
v0.9.8.52
...
v0.9.8.102
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee9fcf38b7 | ||
|
|
5abb24bdd4 | ||
|
|
53f17d3f22 | ||
|
|
b728c38dc1 | ||
|
|
5e57b6ecd0 | ||
|
|
e9ffcdf7c3 | ||
|
|
118657de7c | ||
|
|
34c332504b | ||
|
|
d7a29d68a1 | ||
|
|
eefa02837d | ||
|
|
5b2812fa61 | ||
|
|
e3ddfb88c1 | ||
|
|
664d94aeaa | ||
|
|
e2baf63099 | ||
|
|
c1b7000139 | ||
|
|
6e8333d76f | ||
|
|
c67eddc9d4 | ||
|
|
292cf6fd94 | ||
|
|
69038bca43 | ||
|
|
f05d15ce36 | ||
|
|
98cb349d67 | ||
|
|
a4314ee4d5 | ||
|
|
96097bd25a | ||
|
|
14029e6af2 | ||
|
|
365777141d | ||
|
|
aaa5da8d9b | ||
|
|
b898ab5679 | ||
|
|
b896fa5cc7 | ||
|
|
bca9f6d66b | ||
|
|
d6f71cb2eb | ||
|
|
986d09867c | ||
|
|
97cb2151f9 | ||
|
|
338ac100a1 | ||
|
|
01badcee6a | ||
|
|
302cf1114c | ||
|
|
613e03dc75 | ||
|
|
4267359cb2 | ||
|
|
daac8ec787 | ||
|
|
857adec459 | ||
|
|
b46e10a1a6 | ||
|
|
10799b7e9c | ||
|
|
6bbeaa1738 | ||
|
|
1a0f1cbf9a | ||
|
|
68e708fe96 | ||
|
|
a2166f2327 | ||
|
|
6d55366bdc | ||
|
|
28fcaa81cf | ||
|
|
c5efc2990e | ||
|
|
597010b9a1 | ||
|
|
1f71816256 | ||
|
|
7c3618d2b5 | ||
|
|
df9038039c | ||
|
|
9a4b23976a | ||
|
|
8732e0fe5e | ||
|
|
c23b84c4d5 | ||
|
|
345b6a792a |
@@ -12,6 +12,7 @@ on:
|
||||
paths:
|
||||
- "Daybreak/**"
|
||||
- "Daybreak.Installer/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -48,10 +49,6 @@ jobs:
|
||||
env:
|
||||
LatestReleaseTag: ${{steps.getLatestTag.outputs.tag}}
|
||||
|
||||
- name: Print changelog
|
||||
run: |
|
||||
echo "${{ env.Changelog }}"
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
env:
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreal.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreak.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.x'
|
||||
dotnet-version: '7.x'
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
@@ -14,6 +14,12 @@ if (File.Exists(tempFile) is false)
|
||||
return;
|
||||
}
|
||||
|
||||
while (Process.GetProcesses().Where(p => p.ProcessName == "Daybreak").FirstOrDefault()?.HasExited is false)
|
||||
{
|
||||
Console.WriteLine($"Detected Daybreak process is still running. Waiting 5s and retrying");
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
|
||||
Console.WriteLine("Unpacking files...");
|
||||
try
|
||||
{
|
||||
@@ -23,32 +29,31 @@ catch
|
||||
{
|
||||
|
||||
}
|
||||
Console.WriteLine("Deleting package");
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine($"Failed to delete {tempFile}.\n{e}");
|
||||
}
|
||||
|
||||
Console.WriteLine("Deleting browser caches");
|
||||
try
|
||||
{
|
||||
Directory.Delete("BrowserData", true);
|
||||
}
|
||||
catch(Exception e)
|
||||
catch(Exception)
|
||||
{
|
||||
Console.WriteLine($"Failed to delete BrowserData.\n{e}");
|
||||
}
|
||||
try
|
||||
{
|
||||
Directory.Delete("Daybreak.exe.WebView2", true);
|
||||
}
|
||||
catch(Exception e)
|
||||
catch(Exception)
|
||||
{
|
||||
Console.WriteLine($"Failed to delete Daybreak.exe.WebView2.\n{e}");
|
||||
}
|
||||
|
||||
Console.WriteLine("Deleting package");
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Failed to delete {tempFile}.\n{e}");
|
||||
}
|
||||
|
||||
Console.WriteLine("Launching application");
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Platforms>AnyCPU;x86;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.10.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0-preview-23371-04" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NSubstitute" Version="5.0.0" />
|
||||
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.16">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class InscriptionTests : ItemTestsBase<Inscription>
|
||||
{
|
||||
protected override IEnumerable<Inscription> AllItems { get; } = Inscription.Inscriptions;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class ItemBaseTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TryParse_UnknownId_Fails()
|
||||
{
|
||||
var found = ItemBase.TryParse(int.MaxValue, modifiers: default, out var item);
|
||||
found.Should().BeFalse();
|
||||
item.Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_UnknownId_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = () => ItemBase.Parse(int.MaxValue, modifiers: default);
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TryParse_KnownId_Succeeds()
|
||||
{
|
||||
var found = ItemBase.TryParse(Inscription.WeaponInscription.Id, Inscription.WeaponInscription.Modifiers, out var inscription);
|
||||
found.Should().BeTrue();
|
||||
inscription.Should().Be(Inscription.WeaponInscription);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_KnownId_ReturnsExpected()
|
||||
{
|
||||
var inscription = ItemBase.Parse(Inscription.WeaponInscription.Id, Inscription.WeaponInscription.Modifiers);
|
||||
inscription.Should().Be(Inscription.WeaponInscription);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ItemList_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var itemMap = new Dictionary<ItemBase, int>();
|
||||
|
||||
foreach (var item in ItemBase.AllItems)
|
||||
{
|
||||
if (!itemMap.TryGetValue(item, out _))
|
||||
{
|
||||
itemMap[item] = 0;
|
||||
}
|
||||
|
||||
itemMap[item] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Duplicated item entries: ");
|
||||
foreach (var tuple in itemMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (itemMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
public abstract class ItemTestsBase<T>
|
||||
where T : ItemBase
|
||||
{
|
||||
protected abstract IEnumerable<T> AllItems { get; }
|
||||
|
||||
[TestMethod]
|
||||
public void InscriptionList_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var itemMap = new Dictionary<T, int>();
|
||||
|
||||
foreach (var item in this.AllItems)
|
||||
{
|
||||
if (!itemMap.TryGetValue(item, out _))
|
||||
{
|
||||
itemMap[item] = 0;
|
||||
}
|
||||
|
||||
itemMap[item] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder($"Duplicated {typeof(T).Name} entries: ");
|
||||
foreach (var tuple in itemMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (itemMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InscriptionList_Should_ContainAllNpcs()
|
||||
{
|
||||
var itemMap = new Dictionary<T, bool>();
|
||||
var definedItemFields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(T));
|
||||
foreach (var field in definedItemFields)
|
||||
{
|
||||
var item = field.GetValue(default).Cast<T>();
|
||||
itemMap[item] = false;
|
||||
}
|
||||
|
||||
foreach (var item in this.AllItems)
|
||||
{
|
||||
itemMap[item] = true;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder($"{typeof(T).Name} entries not in list: ");
|
||||
foreach (var tuple in itemMap)
|
||||
{
|
||||
if (tuple.Value is false)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (itemMap.Any(kvp => kvp.Value is false))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class MaterialTests : ItemTestsBase<Material>
|
||||
{
|
||||
protected override IEnumerable<Material> AllItems { get; } = Material.All;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class NpcTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TryParse_UnknownId_Fails()
|
||||
{
|
||||
var found = Npc.TryParse(int.MaxValue, out var npc);
|
||||
found.Should().BeFalse();
|
||||
npc.Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_UnknownId_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = () => Npc.Parse(int.MaxValue);
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TryParse_KnownId_Succeeds()
|
||||
{
|
||||
var found = Npc.TryParse(Npc.Kormir.Ids.FirstOrDefault(), out var npc);
|
||||
found.Should().BeTrue();
|
||||
npc.Should().Be(Npc.Kormir);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_KnownId_ReturnsExpected()
|
||||
{
|
||||
var npc = Npc.Parse(Npc.Kormir.Ids.FirstOrDefault());
|
||||
npc.Should().Be(Npc.Kormir);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NpcList_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var npcMap = new Dictionary<string, int>();
|
||||
|
||||
foreach(var npc in Npc.Npcs)
|
||||
{
|
||||
if (!npcMap.TryGetValue(npc.Name.ToLower(), out _))
|
||||
{
|
||||
npcMap[npc.Name.ToLower()] = 0;
|
||||
}
|
||||
|
||||
npcMap[npc.Name.ToLower()] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Duplicated npc entries: ");
|
||||
foreach(var tuple in npcMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (npcMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NpcList_Should_ContainAllNpcs()
|
||||
{
|
||||
var npcMap = new Dictionary<Npc, bool>();
|
||||
var definedNpcsFields = typeof(Npc).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(Npc));
|
||||
foreach(var field in definedNpcsFields)
|
||||
{
|
||||
var npc = field.GetValue(default).Cast<Npc>();
|
||||
npcMap[npc] = false;
|
||||
}
|
||||
|
||||
foreach(var npc in Npc.Npcs)
|
||||
{
|
||||
npcMap[npc] = true;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Npcs not in list: ");
|
||||
foreach(var tuple in npcMap)
|
||||
{
|
||||
if (tuple.Value is false)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (npcMap.Any(kvp => kvp.Value is false))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Extensions;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class QuestTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TryParse_UnknownId_Fails()
|
||||
{
|
||||
var found = Quest.TryParse(int.MaxValue, out var quest);
|
||||
found.Should().BeFalse();
|
||||
quest.Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_UnknownId_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = () => Quest.Parse(int.MaxValue);
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TryParse_KnownId_Succeeds()
|
||||
{
|
||||
var found = Quest.TryParse(Quest.RaisuPalaceZaishenQuest.Id, out var quest);
|
||||
found.Should().BeTrue();
|
||||
quest.Should().Be(Quest.RaisuPalaceZaishenQuest);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_KnownId_ReturnsExpected()
|
||||
{
|
||||
var quest = Quest.Parse(Quest.RaisuPalaceZaishenQuest.Id);
|
||||
quest.Should().Be(Quest.RaisuPalaceZaishenQuest);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QuestList_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var questMap = new Dictionary<int, int>();
|
||||
|
||||
foreach (var quest in Quest.Quests)
|
||||
{
|
||||
if (!questMap.TryGetValue(quest.Id, out _))
|
||||
{
|
||||
questMap[quest.Id] = 0;
|
||||
}
|
||||
|
||||
questMap[quest.Id] += 1;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Duplicated quest entries: ");
|
||||
foreach (var tuple in questMap)
|
||||
{
|
||||
if (tuple.Value > 1)
|
||||
{
|
||||
errorMessage.Append(tuple.Key);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (questMap.Any(kvp => kvp.Value > 1))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QuestList_Should_ContainAllNpcs()
|
||||
{
|
||||
var questMap = new Dictionary<Quest, bool>();
|
||||
var definedNpcsFields = typeof(Quest).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(Quest));
|
||||
foreach (var field in definedNpcsFields)
|
||||
{
|
||||
var quest = field.GetValue(default).Cast<Quest>();
|
||||
questMap[quest] = false;
|
||||
}
|
||||
|
||||
foreach (var quest in Quest.Quests)
|
||||
{
|
||||
questMap[quest] = true;
|
||||
}
|
||||
|
||||
var errorMessage = new StringBuilder("Quests not in list: ");
|
||||
foreach (var tuple in questMap)
|
||||
{
|
||||
if (tuple.Value is false)
|
||||
{
|
||||
errorMessage.Append(tuple.Key.Name);
|
||||
errorMessage.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (questMap.Any(kvp => kvp.Value is false))
|
||||
{
|
||||
Assert.Fail(errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Tests.Models;
|
||||
|
||||
[TestClass]
|
||||
public sealed class RuneTests : ItemTestsBase<Rune>
|
||||
{
|
||||
protected override IEnumerable<Rune> AllItems { get; } = Rune.Runes;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using Daybreak.Services.BuildTemplates;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using NSubstitute;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Tests.Services;
|
||||
@@ -18,7 +18,7 @@ public class BuildTemplateManagerTests
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
this.buildTemplateManager = new BuildTemplateManager(new Mock<ILogger<BuildTemplateManager>>().Object);
|
||||
this.buildTemplateManager = new BuildTemplateManager(Substitute.For<ILogger<BuildTemplateManager>>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
[OptionsName(Name = "DSOAL")]
|
||||
public sealed class DSOALOptions
|
||||
{
|
||||
[JsonProperty(nameof(Path))]
|
||||
[OptionName(Name = "Path", Description = "The path to the DSOAL installation")]
|
||||
public string? Path { get; set; }
|
||||
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
[OptionName(Name = "Enabled", Description = "If true, the launcher will also launch DSOAL when launching GuildWars")]
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Event Notifier")]
|
||||
public sealed class EventNotifierOptions
|
||||
{
|
||||
[OptionName(Name = "Enabled", Description = "If set to true, Daybreak will notify the user of any event on startup")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
}
|
||||
@@ -11,14 +11,11 @@ public sealed class FocusViewOptions
|
||||
[OptionName(Name = "Enabled", Description = "If true, the focus view is enabled, showing live information from the game")]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[JsonProperty(nameof(MemoryReaderFrequency))]
|
||||
[OptionRange<double>(MinValue = 0, MaxValue = 1000)]
|
||||
[OptionName(Name = "Memory Reader Frequency", Description = "Measured in ms. Sets how often should the launcher poll information from the game. Actual frequency is capped by the memory reading speed")]
|
||||
public double MemoryReaderFrequency { get; set; } = 0;
|
||||
[OptionName(Name = "Inventory Component Enabled", Description = "If true, the focus view will show a component with the inventory contents")]
|
||||
public bool InventoryComponentVisible { get; set; }
|
||||
|
||||
[JsonProperty(nameof(EnablePathfinding))]
|
||||
[OptionName(Name = "Enable Pathfinding", Description = "If true, the mini-map will attempt to produce paths from the player position to objectives")]
|
||||
public bool EnablePathfinding { get; set; } = true;
|
||||
[OptionName(Name = "Minimap Component Enabled", Description = "If true, the focus view will show a minimap component")]
|
||||
public bool MinimapComponentVisible { get; set; }
|
||||
|
||||
[JsonProperty(nameof(ExperienceDisplay))]
|
||||
[OptionName(Name = "Experience Display Mode", Description = "Sets how should the experience display show the information")]
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Memory Cache")]
|
||||
public sealed class ImageCacheOptions
|
||||
{
|
||||
[OptionName(Name = "Image Cache Limit", Description = "The maximum number of MBs that will be used to cache images in memory")]
|
||||
[OptionRange<double>(MinValue = 0d, MaxValue = 1000d)]
|
||||
public double MemoryImageCacheLimit { get; set; } = 100;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Memory Reader")]
|
||||
public sealed class MemoryReaderOptions
|
||||
{
|
||||
[JsonProperty(nameof(MemoryReaderFrequency))]
|
||||
[OptionRange<double>(MinValue = 0, MaxValue = 1000)]
|
||||
[OptionName(Name = "Memory Reader Frequency", Description = "Measured in ms. Sets how often should the launcher polls information from the game. Actual frequency is capped by the memory reading speed")]
|
||||
public double MemoryReaderFrequency { get; set; } = 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Services.Notifications.Models;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsIgnore]
|
||||
internal sealed class NotificationStorageOptions : ILiteCollectionOptions<NotificationDTO>
|
||||
{
|
||||
public string CollectionName => "notifications";
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Pathfinding")]
|
||||
public sealed class PathfindingOptions
|
||||
{
|
||||
[JsonProperty(nameof(EnablePathfinding))]
|
||||
[OptionName(Name = "Enable Pathfinding", Description = "If true, the pathfinder will attempt to produce paths from the player position to objectives")]
|
||||
public bool EnablePathfinding { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(ImprovedPathfinding))]
|
||||
[OptionName(Name = "Distance-Based Pathfinding", Description = "If true, the pathfinder will attempt use an improved algorithm to find paths. Slower but generally more precise")]
|
||||
public bool ImprovedPathfinding { get; set; } = true;
|
||||
}
|
||||
@@ -15,5 +15,5 @@ public sealed class PriceHistoryOptions : ILiteCollectionOptions<TraderQuoteDTO>
|
||||
|
||||
public TimeSpan UpdateInterval { get; set; } = TimeSpan.FromHours(1);
|
||||
|
||||
public Dictionary<int, DateTime> ItemHistoryMetadata { get; set; } = new();
|
||||
public Dictionary<string, DateTime> ItemHistoryMetadata { get; set; } = new();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Sounds")]
|
||||
public sealed class SoundOptions
|
||||
{
|
||||
[OptionName(Name = "Sounds Enabled", Description = "If enabled, the client will play sounds.")]
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Models.Trade;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsIgnore]
|
||||
public sealed class TradeAlertingOptions
|
||||
{
|
||||
public TimeSpan MaxLookbackPeriod { get; set; } = TimeSpan.FromDays(31);
|
||||
public DateTime LastCheckTime { get; set; } = DateTime.MinValue;
|
||||
public List<TradeAlert> Alerts { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Services.TradeChat.Models;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsIgnore]
|
||||
public sealed class TraderMessagesOptions : ILiteCollectionOptions<TraderMessageDTO>
|
||||
{
|
||||
public string CollectionName => "trader_messages";
|
||||
}
|
||||
@@ -55,17 +55,35 @@ using Daybreak.Views.Trade;
|
||||
using System.Net.WebSockets;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Services.Notifications;
|
||||
using Daybreak.Models.Trade;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Daybreak.Services.TradeChat.Models;
|
||||
using Daybreak.Services.Charts;
|
||||
using Daybreak.Services.Images;
|
||||
using Daybreak.Services.Drawing.Modules.Bosses;
|
||||
using Daybreak.Services.InternetChecker;
|
||||
using System;
|
||||
using Daybreak.Services.Sounds;
|
||||
using Daybreak.Services.Notifications.Models;
|
||||
using Daybreak.Models.Notifications.Handling;
|
||||
using Daybreak.Services.TradeChat.Notifications;
|
||||
using Daybreak.Views.Copy;
|
||||
using Daybreak.Services.DSOAL;
|
||||
using Daybreak.Services.Mods;
|
||||
using Daybreak.Views.Onboarding.DSOAL;
|
||||
using Daybreak.Services.Registry;
|
||||
using Daybreak.Services.DSOAL.Actions;
|
||||
using Daybreak.Services.Events;
|
||||
using System.Reflection;
|
||||
using Daybreak.Controls;
|
||||
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
public static class ProjectConfiguration
|
||||
{
|
||||
private const string DaybreakUserAgent = "Daybreak";
|
||||
private const string ChromeImpersonationUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.79";
|
||||
|
||||
public static string? CurrentConfiguration => typeof(ProjectConfiguration).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>()?.Configuration;
|
||||
|
||||
public static void RegisterResolvers(IServiceManager serviceManager)
|
||||
{
|
||||
@@ -81,7 +99,7 @@ public static class ProjectConfiguration
|
||||
.Build()
|
||||
.RegisterHttpClient<BloogumClient>()
|
||||
.WithMessageHandler(SetupLoggingAndMetrics<BloogumClient>)
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.WithDefaultRequestHeadersSetup(SetupChromeImpersonationUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<GraphClient>()
|
||||
.WithMessageHandler(SetupLoggingAndMetrics<GraphClient>)
|
||||
@@ -110,6 +128,14 @@ public static class ProjectConfiguration
|
||||
.RegisterHttpClient<PriceHistoryService>()
|
||||
.WithMessageHandler(SetupLoggingAndMetrics<PriceHistoryService>)
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<InternetCheckingService>()
|
||||
.WithMessageHandler(SetupLoggingAndMetrics<InternetCheckingService>)
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<ChromiumBrowserWrapper>()
|
||||
.WithMessageHandler(SetupLoggingAndMetrics<ChromiumBrowserWrapper>)
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.Build();
|
||||
}
|
||||
|
||||
@@ -154,8 +180,16 @@ public static class ProjectConfiguration
|
||||
services.AddSingleton<IThemeManager, ThemeManager>();
|
||||
services.AddSingleton<INotificationService, NotificationService>();
|
||||
services.AddSingleton<INotificationProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().As<NotificationService>()!);
|
||||
services.AddSingleton<INotificationHandlerProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().As<NotificationService>()!);
|
||||
services.AddSingleton<ILiveChartInitializer, LiveChartInitializer>();
|
||||
services.AddSingleton<IImageCache, ImageCache>();
|
||||
services.AddSingleton<ISoundService, SoundService>();
|
||||
services.AddSingleton<IInternetCheckingService, InternetCheckingService>();
|
||||
services.AddSingleton<IConnectivityStatus, ConnectivityStatus>();
|
||||
services.AddSingleton<INotificationStorage, NotificationStorage>();
|
||||
services.AddSingleton<ITradeAlertingService, TradeAlertingService>();
|
||||
services.AddSingleton<IModsManager, ModsManager>();
|
||||
services.AddSingleton<IGuildwarsMemoryCache, GuildwarsMemoryCache>();
|
||||
services.AddScoped<ICredentialManager, CredentialManager>();
|
||||
services.AddScoped<IApplicationLauncher, ApplicationLauncher>();
|
||||
services.AddScoped<IScreenshotProvider, ScreenshotProvider>();
|
||||
@@ -178,13 +212,17 @@ public static class ProjectConfiguration
|
||||
services.AddScoped<IPathfinder, StupidPathfinder>();
|
||||
services.AddScoped<IDrawingService, DrawingService>();
|
||||
services.AddScoped<IDrawingModuleProducer, DrawingService>(sp => sp.GetRequiredService<IDrawingService>().As<DrawingService>()!);
|
||||
services.AddScoped<IUModService, UModService>();
|
||||
services.AddScoped<IToolboxService, ToolboxService>();
|
||||
services.AddScoped<ITradeChatService<KamadanTradeChatOptions>, TradeChatService<KamadanTradeChatOptions>>();
|
||||
services.AddScoped<ITradeChatService<AscalonTradeChatOptions>, TradeChatService<AscalonTradeChatOptions>>();
|
||||
services.AddScoped<ITraderQuoteService, TraderQuoteService>();
|
||||
services.AddScoped<IPriceHistoryDatabase, PriceHistoryDatabase>();
|
||||
services.AddScoped<IPriceHistoryService, PriceHistoryService>();
|
||||
services.AddScoped<IWordHighlightingService, WordHighlightingService>();
|
||||
services.AddScoped<ITradeHistoryDatabase, TradeHistoryDatabase>();
|
||||
services.AddScoped<IGuildwarsCopyService, GuildwarsCopyService>();
|
||||
services.AddScoped<IItemHashService, ItemHashService>();
|
||||
services.AddScoped<IRegistryService, RegistryService>();
|
||||
services.AddScoped<IEventNotifierService, EventNotifierService>();
|
||||
}
|
||||
|
||||
public static void RegisterViews(IViewProducer viewProducer)
|
||||
@@ -200,6 +238,7 @@ public static class ProjectConfiguration
|
||||
viewProducer.RegisterView<BuildTemplateView>();
|
||||
viewProducer.RegisterView<BuildsListView>();
|
||||
viewProducer.RegisterView<RequestElevationView>();
|
||||
viewProducer.RegisterView<RequestDelevationView>();
|
||||
viewProducer.RegisterView<ScreenChoiceView>();
|
||||
viewProducer.RegisterView<VersionManagementView>();
|
||||
viewProducer.RegisterView<LogsView>();
|
||||
@@ -223,6 +262,17 @@ public static class ProjectConfiguration
|
||||
viewProducer.RegisterView<AscalonTradeChatView>();
|
||||
viewProducer.RegisterView<PriceQuotesView>();
|
||||
viewProducer.RegisterView<PriceHistoryView>();
|
||||
viewProducer.RegisterView<NotificationsView>();
|
||||
viewProducer.RegisterView<TradeAlertsView>();
|
||||
viewProducer.RegisterView<TradeAlertSetupView>();
|
||||
viewProducer.RegisterView<TradeNotificationView>();
|
||||
viewProducer.RegisterView<GuildwarsCopySelectionView>();
|
||||
viewProducer.RegisterView<GuildwarsCopyView>();
|
||||
viewProducer.RegisterView<DSOALInstallingView>();
|
||||
viewProducer.RegisterView<DSOALOnboardingEntryView>();
|
||||
viewProducer.RegisterView<DSOALSwitchView>();
|
||||
viewProducer.RegisterView<DSOALHomepageView>();
|
||||
viewProducer.RegisterView<DSOALBrowserView>();
|
||||
}
|
||||
|
||||
public static void RegisterStartupActions(IStartupActionProducer startupActionProducer)
|
||||
@@ -230,6 +280,7 @@ public static class ProjectConfiguration
|
||||
startupActionProducer.ThrowIfNull();
|
||||
|
||||
startupActionProducer.RegisterAction<RenameInstallerAction>();
|
||||
startupActionProducer.RegisterAction<FixSymbolicLinkStartupAction>();
|
||||
}
|
||||
|
||||
public static void RegisterPostUpdateActions(IPostUpdateActionProducer postUpdateActionProducer)
|
||||
@@ -245,9 +296,22 @@ public static class ProjectConfiguration
|
||||
drawingModuleProducer.RegisterDrawingModule<NeutralEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<AlliedCreatureEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<AllyEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<BossEntityDrawingModule>();
|
||||
|
||||
drawingModuleProducer.RegisterDrawingModule<NeutralBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<WarriorBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<RangerBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<MesmerBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<NecromancerBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<MonkBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<ElementalistBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<AssassinBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<RitualistBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<DervishBossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<ParagonBossEntityDrawingModule>();
|
||||
|
||||
drawingModuleProducer.RegisterDrawingModule<EnemyEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<NpcEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<UnknownEntityDrawingModule>();
|
||||
|
||||
drawingModuleProducer.RegisterDrawingModule<ResurrectionShrineDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<CollectorDrawingModule>();
|
||||
@@ -276,25 +340,56 @@ public static class ProjectConfiguration
|
||||
{
|
||||
optionsProducer.ThrowIfNull();
|
||||
|
||||
optionsProducer.RegisterOptions<LauncherOptions>();
|
||||
optionsProducer.RegisterOptions<SoundOptions>();
|
||||
optionsProducer.RegisterOptions<ThemeOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<BrowserOptions>();
|
||||
optionsProducer.RegisterOptions<BuildSynchronizationOptions>();
|
||||
optionsProducer.RegisterOptions<FocusViewOptions>();
|
||||
optionsProducer.RegisterOptions<LauncherOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<MemoryReaderOptions>();
|
||||
optionsProducer.RegisterOptions<ImageCacheOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<ToolboxOptions>();
|
||||
optionsProducer.RegisterOptions<UModOptions>();
|
||||
optionsProducer.RegisterOptions<DSOALOptions>();
|
||||
|
||||
optionsProducer.RegisterOptions<ScreenManagerOptions>();
|
||||
optionsProducer.RegisterOptions<KamadanTradeChatOptions>();
|
||||
optionsProducer.RegisterOptions<AscalonTradeChatOptions>();
|
||||
optionsProducer.RegisterOptions<LoggingOptions>();
|
||||
optionsProducer.RegisterOptions<PriceHistoryOptions>();
|
||||
optionsProducer.RegisterOptions<TraderQuotesOptions>();
|
||||
optionsProducer.RegisterOptions<PathfindingOptions>();
|
||||
optionsProducer.RegisterOptions<NotificationStorageOptions>();
|
||||
optionsProducer.RegisterOptions<TradeAlertingOptions>();
|
||||
optionsProducer.RegisterOptions<TraderMessagesOptions>();
|
||||
optionsProducer.RegisterOptions<EventNotifierOptions>();
|
||||
}
|
||||
|
||||
public static void RegisterLiteCollections(IServiceCollection services)
|
||||
{
|
||||
RegisterLiteCollection<Models.Log, LoggingOptions>(services);
|
||||
RegisterLiteCollection<TraderQuoteDTO, PriceHistoryOptions>(services);
|
||||
RegisterLiteCollection<NotificationDTO, NotificationStorageOptions>(services);
|
||||
RegisterLiteCollection<TraderMessageDTO, TraderMessagesOptions>(services);
|
||||
}
|
||||
|
||||
public static void RegisterNotificationHandlers(INotificationHandlerProducer notificationHandlerProducer)
|
||||
{
|
||||
notificationHandlerProducer.RegisterNotificationHandler<NoActionHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<MessageBoxHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<TradeMessageNotificationHandler>();
|
||||
notificationHandlerProducer.RegisterNotificationHandler<FixSymbolicLinkNotificationHandler>();
|
||||
}
|
||||
|
||||
public static void RegisterMods(IModsManager modsManager)
|
||||
{
|
||||
modsManager.RegisterMod<IToolboxService, ToolboxService>();
|
||||
modsManager.RegisterMod<IUModService, UModService>();
|
||||
modsManager.RegisterMod<IDSOALService, DSOALService>();
|
||||
modsManager.RegisterMod<IGuildwarsScreenPlacer, GuildwarsScreenPlacer>();
|
||||
}
|
||||
|
||||
private static void RegisterLiteCollection<TCollectionType, TOptionsType>(IServiceCollection services)
|
||||
@@ -313,10 +408,16 @@ public static class ProjectConfiguration
|
||||
httpRequestHeaders.ThrowIfNull().TryAddWithoutValidation("User-Agent", DaybreakUserAgent);
|
||||
}
|
||||
|
||||
private static void SetupChromeImpersonationUserAgent(HttpRequestHeaders httpRequestHeaders)
|
||||
{
|
||||
httpRequestHeaders.ThrowIfNull().TryAddWithoutValidation("User-Agent", ChromeImpersonationUserAgent);
|
||||
}
|
||||
|
||||
private static HttpMessageHandler SetupLoggingAndMetrics<T>(System.IServiceProvider serviceProvider)
|
||||
{
|
||||
var logger = serviceProvider.GetRequiredService<ILogger<T>>();
|
||||
var metricsService = serviceProvider.GetRequiredService<IMetricsService>();
|
||||
|
||||
|
||||
return new MetricsHttpMessageHandler<T>(
|
||||
metricsService,
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<UserControl x:Class="Daybreak.Controls.BagItemContextMenu"
|
||||
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"
|
||||
xmlns:guildwars="clr-namespace:Daybreak.Models.Guildwars"
|
||||
Background="{StaticResource Daybreak.Brushes.Background}"
|
||||
d:DataContext="{d:DesignInstance Type=guildwars:BagItem, IsDesignTimeCreatable=True}"
|
||||
BorderBrush="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel Margin="5, 0, 5, 0">
|
||||
<TextBlock
|
||||
Text="{Binding Item.Name, Mode=OneWay}"
|
||||
FontSize="16"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" />
|
||||
<WrapPanel>
|
||||
<TextBlock
|
||||
Text="Wiki: "
|
||||
FontSize="16"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" />
|
||||
<TextBlock
|
||||
Text="{Binding Item.WikiUrl, Mode=OneWay}"
|
||||
FontSize="16"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonDown="WikiTextBlock_MouseLeftButtonDown"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel>
|
||||
<TextBlock
|
||||
Text="Price history: "
|
||||
FontSize="16"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" />
|
||||
<TextBlock
|
||||
Text="Check"
|
||||
FontSize="16"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonDown="PriceHistoryTextBlock_MouseLeftButtonDown"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,41 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
/// <summary>
|
||||
/// Interaction logic for BagItemContextMenu.xaml
|
||||
/// </summary>
|
||||
public partial class BagItemContextMenu : UserControl
|
||||
{
|
||||
public event EventHandler<ItemBase>? PriceHistoryClicked;
|
||||
public event EventHandler<ItemBase>? WikiClicked;
|
||||
|
||||
public BagItemContextMenu()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void WikiTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not BagItem bagItem ||
|
||||
bagItem.Item is not ItemBase itemBase)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.WikiClicked?.Invoke(this, itemBase);
|
||||
}
|
||||
|
||||
private void PriceHistoryTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not BagItem bagItem ||
|
||||
bagItem.Item is not ItemBase itemBase)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.PriceHistoryClicked?.Invoke(this, itemBase);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +11,8 @@ public partial class AddButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
public ICommand? Click { get; set; }
|
||||
|
||||
public AddButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +21,9 @@ public partial class AddButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class BackButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public BackButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class BackButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class BinButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public BinButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class BinButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Buttons.BrowserButton"
|
||||
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.Buttons"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<local:CircularButton Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Highlight="{StaticResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Stretch="Fill" Width="60" Height="60">
|
||||
<Grid Width="24" Height="24"
|
||||
Margin="5">
|
||||
<Path Data="m7.724,17a15.176,15.176 0 0 0 4.276,7a15.176,15.176 0 0 0 4.276,-7l-8.552,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m7,12a17.764,17.764 0 0 0 0.271,3l9.458,0a17.764,17.764 0 0 0 0.271,-3a17.764,17.764 0 0 0 -0.271,-3l-9.458,0a17.764,17.764 0 0 0 -0.271,3z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m23.606,9l-4.863,0a19.608,19.608 0 0 1 0.257,3a19.608,19.608 0 0 1 -0.257,3l4.863,0a11.618,11.618 0 0 0 0,-6z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m22.9,7a12.025,12.025 0 0 0 -7.87,-6.6a17.922,17.922 0 0 1 3.294,6.6l4.576,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m5,12a19.608,19.608 0 0 1 0.257,-3l-4.863,0a11.618,11.618 0 0 0 0,6l4.863,0a19.608,19.608 0 0 1 -0.257,-3z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m1.1,17a12.025,12.025 0 0 0 7.87,6.6a17.922,17.922 0 0 1 -3.294,-6.6l-4.576,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m15.03,23.6a12.025,12.025 0 0 0 7.87,-6.6l-4.576,0a17.922,17.922 0 0 1 -3.294,6.6z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m16.276,7a15.176,15.176 0 0 0 -4.276,-7a15.176,15.176 0 0 0 -4.276,7l8.552,0z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
<Path Data="m8.97,0.4a12.025,12.025 0 0 0 -7.87,6.6l4.576,0a17.922,17.922 0 0 1 3.294,-6.6z"
|
||||
Fill="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
/// Interaction logic for CopyButton.xaml
|
||||
/// </summary>
|
||||
public partial class BrowserButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public BrowserButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class CancelButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public CancelButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class CancelButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
@@ -10,7 +11,10 @@ namespace Daybreak.Controls.Buttons;
|
||||
/// </summary>
|
||||
public partial class CircularButton : UserControl
|
||||
{
|
||||
public event EventHandler Clicked;
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private Brush highlight = default!;
|
||||
@@ -39,5 +43,9 @@ public partial class CircularButton : UserControl
|
||||
private void Ellipse_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
@@ -9,6 +11,9 @@ public partial class CopyButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public CopyButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -17,5 +22,9 @@ public partial class CopyButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class FilePickerButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public FilePickerButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class FilePickerButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class HelpButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public HelpButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class HelpButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=HorizontalContentAlignment, Mode=OneWay}"
|
||||
TextWrapping="{Binding ElementName=_this, Path=TextWrapping, Mode=OneWay}"
|
||||
TextAlignment="{Binding ElementName=_this, Path=TextAlignment, Mode=OneWay}"
|
||||
Padding="{Binding ElementName=_this, Path=TextPadding, Mode=OneWay}"/>
|
||||
Padding="{Binding ElementName=_this, Path=TextPadding, Mode=OneWay}" />
|
||||
<ContentPresenter
|
||||
Content="{Binding ElementName=_this, Path=ButtonContent, Mode=OneWay}"/>
|
||||
<Rectangle Fill="Transparent"
|
||||
|
||||
@@ -13,12 +13,13 @@ public partial class HighlightButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool highlighted;
|
||||
[GenerateDependencyProperty]
|
||||
private Brush highlightColor = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private FrameworkElement innerContent = default!;
|
||||
[GenerateDependencyProperty(InitialValue = "")]
|
||||
private string title = string.Empty;
|
||||
[GenerateDependencyProperty(InitialValue = HorizontalAlignment.Left)]
|
||||
@@ -52,5 +53,9 @@ public partial class HighlightButton : UserControl
|
||||
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class HomeButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public HomeButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class HomeButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class MaximizeButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public MaximizeButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class MaximizeButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:behaviors="clr-namespace:Daybreak.Behaviors"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
|
||||
@@ -14,6 +14,9 @@ public partial class MenuButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool highlighted;
|
||||
[GenerateDependencyProperty]
|
||||
@@ -45,5 +48,9 @@ public partial class MenuButton : UserControl
|
||||
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class MinusButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public MinusButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class MinusButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<local:CircularButton.Content>
|
||||
<Viewbox Width="60" Height="60">
|
||||
<glyphs:RefreshGlyph Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}" Margin="0, 0, 60, 60"></glyphs:RefreshGlyph>
|
||||
<glyphs:RefreshGlyph Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}" Margin="0, 60, 60, 120"></glyphs:RefreshGlyph>
|
||||
</Viewbox>
|
||||
</local:CircularButton.Content>
|
||||
</local:CircularButton>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
@@ -9,6 +11,9 @@ public partial class RefreshButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public RefreshButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -17,5 +22,9 @@ public partial class RefreshButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class SaveButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public SaveButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class SaveButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
/// <summary>
|
||||
@@ -9,6 +11,9 @@ public partial class StarButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public StarButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -17,5 +22,9 @@ public partial class StarButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Buttons;
|
||||
|
||||
@@ -10,6 +12,9 @@ public partial class SynchronizeButton : UserControl
|
||||
{
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ICommand click = default!;
|
||||
|
||||
public SynchronizeButton()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -18,5 +23,9 @@ public partial class SynchronizeButton : UserControl
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.Clicked?.Invoke(this, e);
|
||||
if (this.Click?.CanExecute(e) is true)
|
||||
{
|
||||
this.Click?.Execute(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Models.Browser;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Options;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Microsoft.Web.WebView2.Wpf;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -35,6 +34,7 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
public static readonly DependencyProperty AddressProperty =
|
||||
DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, string>(nameof(Address));
|
||||
|
||||
private const long MaxBuildBytes = 200;
|
||||
private const string BrowserSearchPlaceholder = "[PLACEHOLDER]";
|
||||
private const string BrowserSearchLink = $"https://www.google.com/search?q={BrowserSearchPlaceholder}";
|
||||
private const string BrowserDownloadLink = "https://developer.microsoft.com/en-us/microsoft-edge/webview2/";
|
||||
@@ -46,11 +46,12 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
|
||||
public event EventHandler<string>? FavoriteUriChanged;
|
||||
public event EventHandler? MaximizeClicked;
|
||||
public event EventHandler<Build>? BuildDecoded;
|
||||
public event EventHandler<DownloadedBuild>? BuildDecoded;
|
||||
public event EventHandler<DownloadPayload>? DownloadingFile;
|
||||
public event EventHandler<string>? DownloadedFile;
|
||||
|
||||
private readonly Task initializationTask;
|
||||
private readonly IHttpClient<ChromiumBrowserWrapper> httpClient;
|
||||
private readonly ILiveOptions<BrowserOptions> liveOptions;
|
||||
private readonly ILogger<ChromiumBrowserWrapper> logger;
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
@@ -93,17 +94,20 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
}
|
||||
|
||||
public ChromiumBrowserWrapper()
|
||||
: this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<BrowserOptions>>(),
|
||||
: this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IHttpClient<ChromiumBrowserWrapper>>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<BrowserOptions>>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBuildTemplateManager>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILogger<ChromiumBrowserWrapper>>())
|
||||
{
|
||||
}
|
||||
|
||||
public ChromiumBrowserWrapper(
|
||||
IHttpClient<ChromiumBrowserWrapper> httpClient,
|
||||
ILiveOptions<BrowserOptions> liveOptions,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> logger)
|
||||
{
|
||||
this.httpClient = httpClient.ThrowIfNull();
|
||||
this.liveOptions = liveOptions.ThrowIfNull();
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull();
|
||||
this.logger = logger.ThrowIfNull();
|
||||
@@ -221,10 +225,12 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
};
|
||||
this.WebBrowser.CoreWebView2.DownloadStarting += (browser, args) =>
|
||||
{
|
||||
if (this.CanDownloadFiles is false)
|
||||
if (!this.CanDownloadFiles)
|
||||
{
|
||||
this.logger?.LogInformation("Downloads are disallowed. Cancelling download");
|
||||
args.Cancel = true;
|
||||
this.CheckForBuildFile(args.DownloadOperation.Uri);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.DownloadsDirectory.IsNullOrWhiteSpace())
|
||||
@@ -250,7 +256,15 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
};
|
||||
this.WebBrowser.NavigationCompleted += (browser, args) => this.Navigating = false;
|
||||
this.WebBrowser.WebMessageReceived += this.CoreWebView2_WebMessageReceived!;
|
||||
this.WebBrowser.CoreWebView2.Settings.AreDevToolsEnabled = false;
|
||||
this.WebBrowser.CoreWebView2.DOMContentLoaded += async (browser, args) =>
|
||||
{
|
||||
if (this.CanDownloadBuild)
|
||||
{
|
||||
await this.WebBrowser.CoreWebView2.ExecuteScriptAsync(Scripts.SendSelectionOnContextMenu);
|
||||
}
|
||||
};
|
||||
|
||||
this.WebBrowser.CoreWebView2.Settings.AreDevToolsEnabled = ProjectConfiguration.CurrentConfiguration == "Debug";
|
||||
this.WebBrowser.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
|
||||
if (this.CanDownloadBuild)
|
||||
{
|
||||
@@ -260,6 +274,42 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
this.browserInitialized = true;
|
||||
}
|
||||
|
||||
private async void CheckForBuildFile(string source)
|
||||
{
|
||||
var scopedLogger = this.logger.CreateScopedLogger(nameof(this.CheckForBuildFile), source);
|
||||
if (!this.CanDownloadBuild)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.IsNullOrWhiteSpace())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await this.httpClient.GetAsync(source);
|
||||
if (result.Content.Headers.ContentLength > MaxBuildBytes)
|
||||
{
|
||||
this.logger.LogInformation($"Content size [{result.Content.Headers.ContentLength}] exceeds max size [{MaxBuildBytes}]");
|
||||
result.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
var content = await result.Content.ReadAsStringAsync();
|
||||
if (!this.buildTemplateManager.TryDecodeTemplate(content, out var build))
|
||||
{
|
||||
this.logger.LogInformation("Could not decode downloaded file");
|
||||
return;
|
||||
}
|
||||
|
||||
build.SourceUrl = this.Address;
|
||||
this.BuildDecoded?.Invoke(this, new DownloadedBuild
|
||||
{
|
||||
Build = build,
|
||||
PreferredName = result.Content.Headers.ContentDisposition?.FileName
|
||||
});
|
||||
}
|
||||
|
||||
private async void RetryInitializeButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
@@ -284,7 +334,12 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Enter)
|
||||
{
|
||||
var input = sender.As<TextBox>().Text;
|
||||
var input = sender.As<TextBox>()?.Text;
|
||||
if (input is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var maybeAddress = SanitizeAddress(input);
|
||||
// If input is address, navigate to address. Otherwise search for the text input in Google
|
||||
if (Uri.TryCreate(maybeAddress, UriKind.Absolute, out _))
|
||||
@@ -304,7 +359,7 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
|
||||
private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs args)
|
||||
{
|
||||
BrowserPayload payload = default!;
|
||||
BrowserPayload? payload = default!;
|
||||
try
|
||||
{
|
||||
payload = args.WebMessageAsJson.Deserialize<BrowserPayload>();
|
||||
@@ -317,7 +372,7 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
if (payload?.Key == BrowserPayload.PayloadKeys.ContextMenu)
|
||||
{
|
||||
var contextMenuPayload = args.WebMessageAsJson.Deserialize<BrowserPayload<OnContextMenuPayload>>();
|
||||
var maybeTemplate = contextMenuPayload.Value!.Selection;
|
||||
var maybeTemplate = contextMenuPayload?.Value?.Selection?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(maybeTemplate))
|
||||
{
|
||||
return;
|
||||
@@ -328,16 +383,16 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.buildTemplateManager.IsTemplate(maybeTemplate) is false)
|
||||
if (this.buildTemplateManager.TryDecodeTemplate(maybeTemplate, out var build) is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
build.SourceUrl = contextMenuPayload?.Value?.Url;
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var build = this.buildTemplateManager.DecodeTemplate(maybeTemplate);
|
||||
this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.ContextMenu.DataContext = build;
|
||||
@@ -374,7 +429,12 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
{
|
||||
var build = this.ContextMenu.DataContext.As<Build>();
|
||||
this.ContextMenu.IsOpen = false;
|
||||
this.BuildDecoded?.Invoke(this, build);
|
||||
if (build is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BuildDecoded?.Invoke(this, new DownloadedBuild { Build = build, PreferredName = this.WebBrowser.CoreWebView2.DocumentTitle });
|
||||
}
|
||||
|
||||
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FocusViewComponents.CurrentMapComponent"
|
||||
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.FocusViewComponents"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
FontSize="18"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Margin="10"
|
||||
Text="Current Map"></TextBlock>
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"></Rectangle>
|
||||
<buttons:MenuButton
|
||||
Title="{Binding Path=Name, Mode=OneWay}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="CurrentMap_MouseLeftButtonDown"></buttons:MenuButton>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,33 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.FocusViewComponents;
|
||||
/// <summary>
|
||||
/// Interaction logic for CurrentMapComponent.xaml
|
||||
/// </summary>
|
||||
public partial class CurrentMapComponent : UserControl
|
||||
{
|
||||
public event EventHandler<string>? NavigateToClicked;
|
||||
|
||||
public CurrentMapComponent()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void CurrentMap_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not Map currentMap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMap.WikiUrl is not string url)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.NavigateToClicked?.Invoke(this, url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FocusViewComponents.CurrentQuestComponent"
|
||||
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.FocusViewComponents"
|
||||
xmlns:templates="clr-namespace:Daybreak.Controls.Templates"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
FontSize="18"
|
||||
Margin="10"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Text="Current Quest"></TextBlock>
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"></Rectangle>
|
||||
<buttons:MenuButton
|
||||
Title="{Binding Path=Name, Mode=OneWay}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="CurrentQuest_MouseLeftButtonDown"></buttons:MenuButton>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,32 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.FocusViewComponents;
|
||||
/// <summary>
|
||||
/// Interaction logic for CurrentQuestComponent.xaml
|
||||
/// </summary>
|
||||
public partial class CurrentQuestComponent : UserControl
|
||||
{
|
||||
public event EventHandler<string>? NavigateToClicked;
|
||||
|
||||
public CurrentQuestComponent()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void CurrentQuest_MouseLeftButtonDown(object _, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not Quest quest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (quest.WikiUrl is not string url)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.NavigateToClicked?.Invoke(this, url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FocusViewComponents.InventoryComponent"
|
||||
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.FocusViewComponents"
|
||||
xmlns:templates="clr-namespace:Daybreak.Controls.Templates"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<templates:BagTemplate BagName="Equipped Items"
|
||||
DataContext="{Binding EquippedItems, Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Backpack"
|
||||
DataContext="{Binding Backpack, Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Belt Pouch"
|
||||
DataContext="{Binding BeltPouch, Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Bag 1"
|
||||
DataContext="{Binding Bags[0], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Bag 2"
|
||||
DataContext="{Binding Bags[1], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Equipment Pack"
|
||||
DataContext="{Binding EquipmentPack, Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Materials"
|
||||
DataContext="{Binding MaterialStorage, Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 1"
|
||||
DataContext="{Binding StoragePanes[0], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 2"
|
||||
DataContext="{Binding StoragePanes[1], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 3"
|
||||
DataContext="{Binding StoragePanes[2], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 4"
|
||||
DataContext="{Binding StoragePanes[3], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 5"
|
||||
DataContext="{Binding StoragePanes[4], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Anniversary Storage"
|
||||
DataContext="{Binding StoragePanes[5], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 6"
|
||||
DataContext="{Binding StoragePanes[6], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 7"
|
||||
DataContext="{Binding StoragePanes[7], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 8"
|
||||
DataContext="{Binding StoragePanes[8], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 9"
|
||||
DataContext="{Binding StoragePanes[9], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 10"
|
||||
DataContext="{Binding StoragePanes[10], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 11"
|
||||
DataContext="{Binding StoragePanes[11], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 12"
|
||||
DataContext="{Binding StoragePanes[12], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
<templates:BagTemplate BagName="Storage Pane 13"
|
||||
DataContext="{Binding StoragePanes[13], Mode=OneWay}"
|
||||
Margin="0, 0, 0, 20"
|
||||
ItemWikiClicked="BagTemplate_ItemWikiClicked"
|
||||
PriceHistoryClicked="BagTemplate_PriceHistoryClicked"
|
||||
ItemClicked="BagTemplate_ItemClicked"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<Grid Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Right">
|
||||
<buttons:MaximizeButton Height="30" Width="30" Margin="5"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Clicked="MaximizeButton_Clicked"></buttons:MaximizeButton>
|
||||
</Grid>
|
||||
<Grid Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Visibility="{Binding ElementName=_this,Path=BagItemMenuVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<templates:BagItemMenu DataContext="{Binding ElementName=_this, Path=SelectedItem, Mode=OneWay}"
|
||||
CloseClicked="BagItemMenu_CloseClicked"
|
||||
ItemWikiClicked="BagItemMenu_ItemWikiClicked"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,58 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Controls.FocusViewComponents;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for InventoryComponent.xaml
|
||||
/// </summary>
|
||||
public partial class InventoryComponent : UserControl
|
||||
{
|
||||
public event EventHandler? MaximizeClicked;
|
||||
public event EventHandler<ItemBase>? ItemWikiClicked;
|
||||
public event EventHandler<ItemBase>? PriceHistoryClicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool bagItemMenuVisible;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private IBagContent selectedItem = default!;
|
||||
|
||||
public InventoryComponent()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void MaximizeButton_Clicked(object _, EventArgs e)
|
||||
{
|
||||
this.MaximizeClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void BagTemplate_ItemWikiClicked(object _, ItemBase e)
|
||||
{
|
||||
this.ItemWikiClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void BagTemplate_PriceHistoryClicked(object _, ItemBase e)
|
||||
{
|
||||
this.PriceHistoryClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void BagTemplate_ItemClicked(object _, IBagContent e)
|
||||
{
|
||||
this.BagItemMenuVisible = true;
|
||||
this.SelectedItem = e;
|
||||
}
|
||||
|
||||
private void BagItemMenu_CloseClicked(object _, EventArgs e)
|
||||
{
|
||||
this.BagItemMenuVisible = false;
|
||||
}
|
||||
|
||||
private void BagItemMenu_ItemWikiClicked(object _, ItemBase e)
|
||||
{
|
||||
this.ItemWikiClicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FocusViewComponents.MainPlayerInformationComponent"
|
||||
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.FocusViewComponents"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
FontSize="18"
|
||||
Margin="10"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Text="{Binding Path=Name, Mode=OneWay}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"></TextBlock>
|
||||
<buttons:HighlightButton
|
||||
Grid.Column="1"
|
||||
Title="Edit Build"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Margin="10, 0, 10, 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Cursor="Hand"
|
||||
FontSize="18"
|
||||
MouseLeftButtonDown="EditBuild_MouseLeftButtonDown"></buttons:HighlightButton>
|
||||
<buttons:HighlightButton
|
||||
Grid.Column="2"
|
||||
Title="Meta Builds"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Margin="10, 0, 0, 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Cursor="Hand"
|
||||
FontSize="18"
|
||||
MouseLeftButtonDown="MetaBuilds_MouseLeftButtonDown"></buttons:HighlightButton>
|
||||
</Grid>
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}" />
|
||||
<buttons:MenuButton
|
||||
Title="{Binding Path=PrimaryProfession.Name, Mode=OneWay}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="PrimaryProfession_MouseLeftButtonDown"></buttons:MenuButton>
|
||||
<buttons:MenuButton
|
||||
Title="{Binding Path=SecondaryProfession.Name, Mode=OneWay}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="SecondaryProfession_MouseLeftButtonDown"></buttons:MenuButton>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,97 @@
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.FocusViewComponents;
|
||||
/// <summary>
|
||||
/// Interaction logic for MainPlayerInformationComponent.xaml
|
||||
/// </summary>
|
||||
public partial class MainPlayerInformationComponent : UserControl
|
||||
{
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
private readonly IViewManager viewManager;
|
||||
|
||||
public event EventHandler<string>? NavigateToClicked;
|
||||
|
||||
public MainPlayerInformationComponent()
|
||||
: this(
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBuildTemplateManager>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>())
|
||||
{
|
||||
}
|
||||
|
||||
public MainPlayerInformationComponent(
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
IViewManager viewManager)
|
||||
{
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull();
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void MetaBuilds_MouseLeftButtonDown(object _, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not MainPlayerInformation mainPlayer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainPlayer.PrimaryProfession is not null &&
|
||||
mainPlayer.PrimaryProfession != Profession.None &&
|
||||
mainPlayer.PrimaryProfession.BuildsUrl is string url)
|
||||
{
|
||||
this.NavigateToClicked?.Invoke(this, url);
|
||||
}
|
||||
}
|
||||
|
||||
private void PrimaryProfession_MouseLeftButtonDown(object _, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not MainPlayerInformation mainPlayer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainPlayer.PrimaryProfession is not null &&
|
||||
mainPlayer.PrimaryProfession != Profession.None &&
|
||||
mainPlayer.PrimaryProfession.WikiUrl is string url)
|
||||
{
|
||||
this.NavigateToClicked?.Invoke(this, url);
|
||||
}
|
||||
}
|
||||
|
||||
private void SecondaryProfession_MouseLeftButtonDown(object _, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not MainPlayerInformation mainPlayer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainPlayer.SecondaryProfession is not null &&
|
||||
mainPlayer.SecondaryProfession != Profession.None &&
|
||||
mainPlayer.SecondaryProfession.WikiUrl is string url)
|
||||
{
|
||||
this.NavigateToClicked?.Invoke(this, url);
|
||||
}
|
||||
}
|
||||
|
||||
private void EditBuild_MouseLeftButtonDown(object _, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not MainPlayerInformation mainPlayer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainPlayer.CurrentBuild is Build build)
|
||||
{
|
||||
var buildEntry = this.buildTemplateManager.CreateBuild();
|
||||
buildEntry.Build = build;
|
||||
this.viewManager.ShowView<BuildTemplateView>(buildEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FocusViewComponents.PlayerResourcesComponent"
|
||||
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.FocusViewComponents"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:BooleanToGridLengthConverter x:Key="ResourceBarGridLengthConverter" VisibleValue="*" />
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.1*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.3*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="0.1*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:VerticalResourceBar
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="3"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=CurrentExperienceInLevel, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=NextLevelExperienceThreshold, Mode=OneWay}"
|
||||
Text="{Binding ElementName=_this,Path=ExperienceBarText, Mode=OneWay}"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Experience}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonDown="ExperienceBar_MouseLeftButtonDown">
|
||||
<controls:VerticalResourceBar.OpacityMask>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<GeometryDrawing Brush="#FFFFFFFF">
|
||||
<GeometryDrawing.Geometry>
|
||||
<PathGeometry>
|
||||
<PathGeometry.Figures>
|
||||
<PathFigure IsClosed="True" StartPoint="5, 1">
|
||||
<PathSegmentCollection>
|
||||
<LineSegment Point="1, 5"></LineSegment>
|
||||
<LineSegment Point="5, 9"></LineSegment>
|
||||
<LineSegment Point="15, 9"></LineSegment>
|
||||
<LineSegment Point="19, 5"></LineSegment>
|
||||
<LineSegment Point="15, 1"></LineSegment>
|
||||
</PathSegmentCollection>
|
||||
</PathFigure>
|
||||
</PathGeometry.Figures>
|
||||
</PathGeometry>
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</controls:VerticalResourceBar.OpacityMask>
|
||||
</controls:VerticalResourceBar>
|
||||
<Viewbox
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="3"
|
||||
Stretch="Fill">
|
||||
<Polygon Points="0, 3.94, 3.2, 8, 10.9, 8, 13.9, 3.94, 10.9, 0, 3.1, 0"
|
||||
StrokeThickness="0.08"
|
||||
Stroke="{DynamicResource MahApps.Brushes.ThemeForeground}"></Polygon>
|
||||
</Viewbox>
|
||||
<Grid
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Grid.RowSpan="2">
|
||||
<Grid.OpacityMask>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<GeometryDrawing Brush="#FFFFFFFF">
|
||||
<GeometryDrawing.Geometry>
|
||||
<PathGeometry>
|
||||
<PathGeometry.Figures>
|
||||
<PathFigure IsClosed="True" StartPoint="1, 1">
|
||||
<PathSegmentCollection>
|
||||
<LineSegment Point="1, 9"></LineSegment>
|
||||
<LineSegment Point="21, 9"></LineSegment>
|
||||
<LineSegment Point="19, 5"></LineSegment>
|
||||
<LineSegment Point="21, 1"></LineSegment>
|
||||
</PathSegmentCollection>
|
||||
</PathFigure>
|
||||
</PathGeometry.Figures>
|
||||
</PathGeometry>
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Grid.OpacityMask>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="0"
|
||||
CurrentResourceValue="{Binding Path=User.User.CurrentKurzickPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding Path=User.User.MaxKurzickPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Kurzick}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=KurzickBarText, Mode=OneWay}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
MouseLeftButtonDown="KurzickBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="1"
|
||||
CurrentResourceValue="{Binding Path=User.User.CurrentLuxonPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding Path=User.User.MaxLuxonPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Luxon}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=LuxonBarText, Mode=OneWay}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
MouseLeftButtonDown="LuxonBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="2"
|
||||
CurrentResourceValue="{Binding Path=User.User.CurrentImperialPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding Path=User.User.MaxImperialPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Imperial}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
Text="{Binding ElementName=_this, Path=ImperialBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="ImperialBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="3"
|
||||
CurrentResourceValue="{Binding Path=User.User.CurrentBalthazarPoints, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding Path=User.User.MaxBalthazarPoints, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Balthazar}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
Text="{Binding ElementName=_this, Path=BalthazarBarText, Mode=OneWay}"
|
||||
MouseLeftButtonDown="BalthazarBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
</Grid>
|
||||
<Viewbox
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Grid.RowSpan="2"
|
||||
Stretch="Fill">
|
||||
<Polygon Points="0, 10.1, 21.5, 10.1, 19.4, 5, 21.5, 0.1, 0, 0.1"
|
||||
StrokeThickness="0.08"
|
||||
Width="21.5"
|
||||
Height="10.2"
|
||||
Stroke="{DynamicResource MahApps.Brushes.ThemeForeground}"></Polygon>
|
||||
</Viewbox>
|
||||
<Grid
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
Grid.Column="3"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Grid.RowSpan="2">
|
||||
<Grid.OpacityMask>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<GeometryDrawing Brush="#FFFFFFFF">
|
||||
<GeometryDrawing.Geometry>
|
||||
<PathGeometry>
|
||||
<PathGeometry.Figures>
|
||||
<PathFigure IsClosed="True" StartPoint="1, 1">
|
||||
<PathSegmentCollection>
|
||||
<LineSegment Point="3, 5"></LineSegment>
|
||||
<LineSegment Point="1, 9"></LineSegment>
|
||||
<LineSegment Point="21, 9"></LineSegment>
|
||||
<LineSegment Point="21, 1"></LineSegment>
|
||||
</PathSegmentCollection>
|
||||
</PathFigure>
|
||||
</PathGeometry.Figures>
|
||||
</PathGeometry>
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Grid.OpacityMask>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="{Binding ElementName=_this, Path=Vanquishing, Mode=OneWay, Converter={StaticResource ResourceBarGridLengthConverter}}"></RowDefinition>
|
||||
<RowDefinition Height="{Binding ElementName=_this, Path=TitleActive, Mode=OneWay, Converter={StaticResource ResourceBarGridLengthConverter}}"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="0"
|
||||
CurrentResourceValue="{Binding Path=Session.Session.FoesKilled, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=TotalFoes, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Vanquish}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=VanquishingText, Mode=OneWay}"
|
||||
FillAlignment="Right"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
Visibility="{Binding ElementName=_this, Path=Vanquishing, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
MouseLeftButtonDown="VanquishingBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="1"
|
||||
CurrentResourceValue="{Binding ElementName=_this, Path=PointsInCurrentRank, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding ElementName=_this, Path=PointsForNextRank, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Rank}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=TitleText, Mode=OneWay}"
|
||||
FillAlignment="Right"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
Visibility="{Binding ElementName=_this, Path=TitleActive, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}" />
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="2"
|
||||
CurrentResourceValue="{Binding Path=Player.PlayerInformation.CurrentHealth, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding Path=Player.PlayerInformation.MaxHealth, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Health}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=HealthBarText, Mode=OneWay}"
|
||||
FillAlignment="Right"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
MouseLeftButtonDown="HealthBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
<controls:HorizontalResourceBar
|
||||
Margin="0, 2, 0, 2"
|
||||
Grid.Row="3"
|
||||
CurrentResourceValue="{Binding Path=Player.PlayerInformation.CurrentEnergy, Mode=OneWay}"
|
||||
MaxResourceValue="{Binding Path=Player.PlayerInformation.MaxEnergy, Mode=OneWay}"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
BarColor="{DynamicResource Daybreak.Brushes.Energy}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="14"
|
||||
Cursor="Hand"
|
||||
Text="{Binding ElementName=_this, Path=EnergyBarText, Mode=OneWay}"
|
||||
FillAlignment="Right"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
MouseLeftButtonDown="EnergyBar_MouseLeftButtonDown"></controls:HorizontalResourceBar>
|
||||
</Grid>
|
||||
<Viewbox
|
||||
Grid.Column="3"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
Grid.RowSpan="2"
|
||||
Stretch="Fill">
|
||||
<Polygon Points="0, 10.1, 21.5, 10.1, 21.5, 0.1, 0, 0.1, 2.1, 5"
|
||||
StrokeThickness="0.08"
|
||||
HorizontalAlignment="Right"
|
||||
Height="10.2"
|
||||
Width="21.49"
|
||||
Stroke="{DynamicResource MahApps.Brushes.ThemeForeground}"></Polygon>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,488 @@
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.Experience;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.FocusViewComponents;
|
||||
/// <summary>
|
||||
/// Interaction logic for PlayerResourcesComponent.xaml
|
||||
/// </summary>
|
||||
public partial class PlayerResourcesComponent : UserControl
|
||||
{
|
||||
private readonly IExperienceCalculator experienceCalculator;
|
||||
private readonly ILiveUpdateableOptions<FocusViewOptions> liveOptions;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private double currentExperienceInLevel;
|
||||
[GenerateDependencyProperty]
|
||||
private double nextLevelExperienceThreshold;
|
||||
[GenerateDependencyProperty]
|
||||
private string experienceBarText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private string luxonBarText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private string kurzickBarText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private string imperialBarText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private string balthazarBarText = string.Empty;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private int pointsInCurrentRank;
|
||||
[GenerateDependencyProperty]
|
||||
private int pointsForNextRank;
|
||||
[GenerateDependencyProperty]
|
||||
private bool titleActive;
|
||||
[GenerateDependencyProperty]
|
||||
private string titleText = string.Empty;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string healthBarText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private string energyBarText = string.Empty;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool vanquishing;
|
||||
[GenerateDependencyProperty]
|
||||
private int totalFoes;
|
||||
[GenerateDependencyProperty]
|
||||
private string vanquishingText = string.Empty;
|
||||
|
||||
public PlayerResourcesComponent()
|
||||
: this(
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IExperienceCalculator>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveUpdateableOptions<FocusViewOptions>>())
|
||||
{
|
||||
}
|
||||
|
||||
public PlayerResourcesComponent(
|
||||
IExperienceCalculator experienceCalculator,
|
||||
ILiveUpdateableOptions<FocusViewOptions> liveOptions)
|
||||
{
|
||||
this.experienceCalculator = experienceCalculator.ThrowIfNull();
|
||||
this.liveOptions = liveOptions.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == DataContextProperty)
|
||||
{
|
||||
this.UpdateGameData();
|
||||
}
|
||||
}
|
||||
|
||||
private void ExperienceBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.ExperienceDisplay)
|
||||
{
|
||||
case Configuration.FocusView.ExperienceDisplay.CurrentLevelCurrentAndCurrentLevelMax:
|
||||
this.liveOptions.Value.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.TotalCurretAndTotalMax;
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.TotalCurretAndTotalMax:
|
||||
this.liveOptions.Value.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.RemainingUntilNextLevel;
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.RemainingUntilNextLevel:
|
||||
this.liveOptions.Value.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.Percentage:
|
||||
this.liveOptions.Value.ExperienceDisplay = Configuration.FocusView.ExperienceDisplay.CurrentLevelCurrentAndCurrentLevelMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateExperienceText();
|
||||
}
|
||||
|
||||
private void LuxonBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.LuxonPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveOptions.Value.LuxonPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveOptions.Value.LuxonPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveOptions.Value.LuxonPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateLuxonText();
|
||||
}
|
||||
|
||||
private void KurzickBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.KurzickPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveOptions.Value.KurzickPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveOptions.Value.KurzickPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveOptions.Value.KurzickPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateKurzickText();
|
||||
}
|
||||
|
||||
private void ImperialBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.ImperialPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveOptions.Value.ImperialPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveOptions.Value.ImperialPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveOptions.Value.ImperialPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateImperialText();
|
||||
}
|
||||
|
||||
private void BalthazarBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.BalthazarPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveOptions.Value.BalthazarPointsDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveOptions.Value.BalthazarPointsDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveOptions.Value.BalthazarPointsDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateBalthazarText();
|
||||
}
|
||||
|
||||
private void VanquishingBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.VanquishingDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveOptions.Value.VanquishingDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveOptions.Value.VanquishingDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveOptions.Value.VanquishingDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateVanquishingText();
|
||||
}
|
||||
|
||||
private void HealthBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.HealthDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveOptions.Value.HealthDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveOptions.Value.HealthDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveOptions.Value.HealthDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateHealthText();
|
||||
}
|
||||
|
||||
private void EnergyBar_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
switch (this.liveOptions.Value.EnergyDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.liveOptions.Value.EnergyDisplay = Configuration.FocusView.PointsDisplay.Remaining;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.liveOptions.Value.EnergyDisplay = Configuration.FocusView.PointsDisplay.Percentage;
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.liveOptions.Value.EnergyDisplay = Configuration.FocusView.PointsDisplay.CurrentAndMax;
|
||||
break;
|
||||
}
|
||||
|
||||
this.liveOptions.UpdateOption();
|
||||
this.UpdateEnergyText();
|
||||
}
|
||||
|
||||
private void UpdateGameData()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.User?.User is null ||
|
||||
mainPlayerResourceContext.Session?.Session is null ||
|
||||
mainPlayerResourceContext.Player?.PlayerInformation is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.CurrentExperienceInLevel = this.experienceCalculator.GetExperienceForCurrentLevel(mainPlayerResourceContext.Player.PlayerInformation.Experience);
|
||||
this.NextLevelExperienceThreshold = this.experienceCalculator.GetNextExperienceThreshold(mainPlayerResourceContext.Player.PlayerInformation.Experience);
|
||||
this.TotalFoes = (int)(mainPlayerResourceContext.Session.Session.FoesKilled + mainPlayerResourceContext.Session.Session.FoesToKill);
|
||||
this.Vanquishing = mainPlayerResourceContext.Session.Session.FoesToKill + mainPlayerResourceContext.Session.Session.FoesKilled > 0U;
|
||||
this.TitleActive = mainPlayerResourceContext.Player.PlayerInformation.TitleInformation is not null && mainPlayerResourceContext.Player.PlayerInformation.TitleInformation.IsValid;
|
||||
|
||||
if (mainPlayerResourceContext.Player.PlayerInformation.TitleInformation is TitleInformation titleInformation && titleInformation.IsValid)
|
||||
{
|
||||
if (titleInformation.MaxTierNumber == titleInformation.TierNumber)
|
||||
{
|
||||
this.PointsInCurrentRank = (int)titleInformation.CurrentPoints!;
|
||||
this.PointsForNextRank = (int)titleInformation.CurrentPoints!;
|
||||
}
|
||||
else if (titleInformation.IsPercentage is false)
|
||||
{
|
||||
this.PointsInCurrentRank = (int)((uint)titleInformation.CurrentPoints! - (uint)titleInformation.PointsForCurrentRank!);
|
||||
this.PointsForNextRank = (int)((uint)titleInformation.PointsForNextRank! - (uint)titleInformation.PointsForCurrentRank!);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.PointsInCurrentRank = (int)(uint)titleInformation.CurrentPoints!;
|
||||
this.PointsForNextRank = (int)(uint)titleInformation.PointsForNextRank!;
|
||||
}
|
||||
}
|
||||
|
||||
this.UpdateExperienceText();
|
||||
this.UpdateLuxonText();
|
||||
this.UpdateKurzickText();
|
||||
this.UpdateImperialText();
|
||||
this.UpdateBalthazarText();
|
||||
this.UpdateVanquishingText();
|
||||
this.UpdateHealthText();
|
||||
this.UpdateEnergyText();
|
||||
this.UpdateTitleText();
|
||||
}
|
||||
|
||||
private void UpdateExperienceText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.Player?.PlayerInformation is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.ExperienceDisplay)
|
||||
{
|
||||
case Configuration.FocusView.ExperienceDisplay.CurrentLevelCurrentAndCurrentLevelMax:
|
||||
var currentExperienceInLevel = this.experienceCalculator.GetExperienceForCurrentLevel(mainPlayerResourceContext.Player.PlayerInformation.Experience);
|
||||
var nextLevelExperienceThreshold = this.experienceCalculator.GetNextExperienceThreshold(mainPlayerResourceContext.Player.PlayerInformation.Experience);
|
||||
this.ExperienceBarText = $"{(int)currentExperienceInLevel} / {(int)nextLevelExperienceThreshold} XP";
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.TotalCurretAndTotalMax:
|
||||
var currentTotalExperience = mainPlayerResourceContext.Player.PlayerInformation.Experience;
|
||||
var requiredTotalExperience = this.experienceCalculator.GetTotalExperienceForNextLevel(currentTotalExperience);
|
||||
this.ExperienceBarText = $"{(int)currentTotalExperience} / {(int)requiredTotalExperience} XP";
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.RemainingUntilNextLevel:
|
||||
var remainingExperience = this.experienceCalculator.GetRemainingExperienceForNextLevel(mainPlayerResourceContext.Player.PlayerInformation.Experience);
|
||||
this.ExperienceBarText = $"Remaining {(int)remainingExperience} XP";
|
||||
break;
|
||||
case Configuration.FocusView.ExperienceDisplay.Percentage:
|
||||
var currentExperienceInLevel2 = this.experienceCalculator.GetExperienceForCurrentLevel(mainPlayerResourceContext.Player.PlayerInformation.Experience);
|
||||
var nextLevelExperienceThreshold2 = this.experienceCalculator.GetNextExperienceThreshold(mainPlayerResourceContext.Player.PlayerInformation.Experience);
|
||||
this.ExperienceBarText = $"{(int)((double)currentExperienceInLevel2 / (double)nextLevelExperienceThreshold2 * 100)}% XP";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLuxonText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.User?.User is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.LuxonPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.LuxonBarText = $"{mainPlayerResourceContext.User.User.CurrentLuxonPoints} / {mainPlayerResourceContext.User.User.MaxLuxonPoints} Luxon Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.LuxonBarText = $"Remaining {mainPlayerResourceContext.User.User.MaxLuxonPoints - mainPlayerResourceContext.User.User.CurrentLuxonPoints} Luxon Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.LuxonBarText = $"{(int)((double)mainPlayerResourceContext.User.User.CurrentLuxonPoints / (double)mainPlayerResourceContext.User.User.MaxLuxonPoints * 100)}% Luxon Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateKurzickText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.User?.User is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.KurzickPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.KurzickBarText = $"{mainPlayerResourceContext.User.User.CurrentKurzickPoints} / {mainPlayerResourceContext.User.User.MaxKurzickPoints} Kurzick Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.KurzickBarText = $"Remaining {mainPlayerResourceContext.User.User!.MaxKurzickPoints - mainPlayerResourceContext.User.User.CurrentKurzickPoints} Kurzick Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.KurzickBarText = $"{(int)((double)mainPlayerResourceContext.User.User.CurrentKurzickPoints / (double)mainPlayerResourceContext.User.User.MaxKurzickPoints * 100)}% Kurzick Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateImperialText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.User?.User is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.ImperialPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.ImperialBarText = $"{mainPlayerResourceContext.User.User!.CurrentImperialPoints} / {mainPlayerResourceContext.User.User.MaxImperialPoints} Imperial Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.ImperialBarText = $"Remaining {mainPlayerResourceContext.User.User!.MaxImperialPoints - mainPlayerResourceContext.User.User.CurrentImperialPoints} Imperial Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.ImperialBarText = $"{(int)((double)mainPlayerResourceContext.User.User!.CurrentImperialPoints / (double)mainPlayerResourceContext.User.User.MaxImperialPoints * 100)}% Imperial Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBalthazarText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.User?.User is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.BalthazarPointsDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.BalthazarBarText = $"{mainPlayerResourceContext.User.User.CurrentBalthazarPoints} / {mainPlayerResourceContext.User.User.MaxBalthazarPoints} Balthazar Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.BalthazarBarText = $"Remaining {mainPlayerResourceContext.User.User.MaxBalthazarPoints - mainPlayerResourceContext.User.User.CurrentBalthazarPoints} Balthazar Points";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.BalthazarBarText = $"{(int)((double)mainPlayerResourceContext.User.User.CurrentBalthazarPoints / (double)mainPlayerResourceContext.User.User.MaxBalthazarPoints * 100)}% Balthazar Points";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVanquishingText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.Session?.Session is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.VanquishingDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.VanquishingText = $"{mainPlayerResourceContext.Session.Session.FoesKilled} / {(int)this.TotalFoes} Foes Killed";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.VanquishingText = $"Remaining {mainPlayerResourceContext.Session.Session.FoesToKill} Foes";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.VanquishingText = $"{(int)((double)mainPlayerResourceContext.Session.Session.FoesKilled / (double)this.TotalFoes * 100)}% Foes Killed";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHealthText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.Player?.PlayerInformation is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.HealthDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.HealthBarText = $"{(int)mainPlayerResourceContext.Player.PlayerInformation.CurrentHealth} / {(int)mainPlayerResourceContext.Player.PlayerInformation.MaxHealth} Health";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.HealthBarText = $"Remaining {(int)mainPlayerResourceContext.Player.PlayerInformation.CurrentHealth} Health";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.HealthBarText = $"{(int)(mainPlayerResourceContext.Player.PlayerInformation.CurrentHealth / mainPlayerResourceContext.Player.PlayerInformation.MaxHealth * 100)}% Health";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEnergyText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.Player?.PlayerInformation is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.liveOptions.Value.EnergyDisplay)
|
||||
{
|
||||
case Configuration.FocusView.PointsDisplay.CurrentAndMax:
|
||||
this.EnergyBarText = $"{(int)mainPlayerResourceContext.Player.PlayerInformation.CurrentEnergy} / {(int)mainPlayerResourceContext.Player.PlayerInformation.MaxEnergy} Energy";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Remaining:
|
||||
this.EnergyBarText = $"Remaining {(int)mainPlayerResourceContext.Player.PlayerInformation.CurrentEnergy} Energy";
|
||||
break;
|
||||
case Configuration.FocusView.PointsDisplay.Percentage:
|
||||
this.EnergyBarText = $"{(int)(mainPlayerResourceContext.Player.PlayerInformation.CurrentEnergy / mainPlayerResourceContext.Player.PlayerInformation.MaxEnergy * 100)}% Energy";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTitleText()
|
||||
{
|
||||
if (this.DataContext is not MainPlayerResourceContext mainPlayerResourceContext ||
|
||||
mainPlayerResourceContext.Player?.PlayerInformation is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainPlayerResourceContext.Player.PlayerInformation.TitleInformation?.IsPercentage is true)
|
||||
{
|
||||
this.TitleText = $"{(double?)mainPlayerResourceContext.Player.PlayerInformation.TitleInformation?.CurrentPoints / 10d}% Rank Progress";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.TitleText = $"{mainPlayerResourceContext.Player.PlayerInformation.TitleInformation?.CurrentPoints}/{mainPlayerResourceContext.Player.PlayerInformation.TitleInformation?.PointsForNextRank} Rank Progress";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FocusViewComponents.QuestLogComponent"
|
||||
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.FocusViewComponents"
|
||||
xmlns:templates="clr-namespace:Daybreak.Controls.Templates"
|
||||
x:Name="_this"
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Grid.Row="0"
|
||||
FontSize="18"
|
||||
Padding="10"
|
||||
Text="Quest Log"></TextBlock>
|
||||
<Rectangle Height="1"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Bottom"></Rectangle>
|
||||
<ScrollViewer
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
Grid.Row="1">
|
||||
<templates:QuestLogTemplate
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Quests="{Binding Mode=OneWay}"
|
||||
MapClicked="QuestLogTemplate_MapClicked"
|
||||
QuestClicked="QuestLogTemplate_QuestClicked">
|
||||
</templates:QuestLogTemplate>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,37 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.FocusViewComponents;
|
||||
/// <summary>
|
||||
/// Interaction logic for QuestLogComponent.xaml
|
||||
/// </summary>
|
||||
public partial class QuestLogComponent : UserControl
|
||||
{
|
||||
public event EventHandler<string>? NavigateToClicked;
|
||||
|
||||
public QuestLogComponent()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void QuestLogTemplate_MapClicked(object _, Map e)
|
||||
{
|
||||
if (e is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.NavigateToClicked?.Invoke(this, e.WikiUrl!);
|
||||
}
|
||||
|
||||
private void QuestLogTemplate_QuestClicked(object _, Quest e)
|
||||
{
|
||||
if (e is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.NavigateToClicked?.Invoke(this, e.WikiUrl!);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<UserControl x:Class="Daybreak.Controls.FocusViewComponents.TitleInformationComponent"
|
||||
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.FocusViewComponents"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
DataContextChanged="UserControl_DataContextChanged"
|
||||
x:Name="_this"
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
FontSize="18"
|
||||
Margin="10"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Text="Title Track"
|
||||
HorizontalAlignment="Left"></TextBlock>
|
||||
<buttons:HighlightButton
|
||||
Grid.Column="1"
|
||||
Title="{Binding Path=Title.Name, Mode=OneWay}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Cursor="Hand"
|
||||
FontSize="18"
|
||||
MouseLeftButtonDown="Title_MouseLeftButtonDown"></buttons:HighlightButton>
|
||||
</Grid>
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"></Rectangle>
|
||||
<buttons:MenuButton
|
||||
Title="{Binding ElementName=_this, Path=TitleRankName, Mode=OneWay}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Cursor="Hand"
|
||||
FontSize="20"
|
||||
MouseLeftButtonDown="Title_MouseLeftButtonDown"></buttons:MenuButton>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,54 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.FocusViewComponents;
|
||||
/// <summary>
|
||||
/// Interaction logic for TitleInformationComponent.xaml
|
||||
/// </summary>
|
||||
public partial class TitleInformationComponent : UserControl
|
||||
{
|
||||
public event EventHandler<string>? NavigateToClicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string titleRankName = string.Empty;
|
||||
|
||||
public TitleInformationComponent()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void Title_MouseLeftButtonDown(object _, MouseButtonEventArgs __)
|
||||
{
|
||||
if (this.DataContext is not TitleInformation titleInformation ||
|
||||
titleInformation.Title is not Title title ||
|
||||
title.WikiUrl is not string url)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.NavigateToClicked?.Invoke(this, url);
|
||||
}
|
||||
|
||||
private void UserControl_DataContextChanged(object _, DependencyPropertyChangedEventArgs __)
|
||||
{
|
||||
if (this.DataContext is not TitleInformation titleInformation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (titleInformation.Title is not null &&
|
||||
titleInformation.Title.Tiers!.Count > titleInformation.TierNumber - 1)
|
||||
{
|
||||
var rankIndex = (int)titleInformation.TierNumber! - 1;
|
||||
this.TitleRankName = $"{titleInformation.Title.Tiers![rankIndex]} ({titleInformation.TierNumber}/{titleInformation.MaxTierNumber})";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.TitleRankName = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public partial class LivingEntityContextMenu : UserControl
|
||||
|
||||
private void NpcDefinitionTextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.LivingEntityContextMenuClicked?.Invoke(this, this.DataContext as LivingEntity? ?? default);
|
||||
this.LivingEntityContextMenuClicked?.Invoke(this, this.DataContext as LivingEntity ?? default);
|
||||
}
|
||||
|
||||
private void PrimaryProfessionTextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
|
||||
@@ -19,6 +19,6 @@ public partial class MapIconContextMenu : UserControl
|
||||
|
||||
private void TextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.MapIconContextMenuClicked?.Invoke(this, this.DataContext as MapIcon? ?? default);
|
||||
this.MapIconContextMenuClicked?.Invoke(this, this.DataContext as MapIcon ?? default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,16 @@
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
xmlns:options="clr-namespace:Daybreak.Controls.Options"
|
||||
Loaded="UserControl_Loaded"
|
||||
Unloaded="UserControl_Unloaded"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<local:ExpandableMenuSection
|
||||
SectionTitle="Guild Wars" Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
@@ -20,28 +27,55 @@
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="GameCompanionButton_Clicked">
|
||||
</buttons:MenuButton>
|
||||
Clicked="GameCompanionButton_Clicked" />
|
||||
<buttons:MenuButton Title="Manage builds"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="ManageBuildsButton_Clicked">
|
||||
</buttons:MenuButton>
|
||||
Clicked="ManageBuildsButton_Clicked" />
|
||||
<buttons:MenuButton Title="Download Guild Wars"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="DownloadGuildwarsButton_Clicked">
|
||||
</buttons:MenuButton>
|
||||
Clicked="DownloadGuildwarsButton_Clicked" />
|
||||
<buttons:MenuButton Title="Copy Guild Wars"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="CopyGuildwarsButton_Clicked" />
|
||||
</local:ExpandableMenuSection.Children>
|
||||
</local:ExpandableMenuSection>
|
||||
<Grid>
|
||||
<TextBlock FontSize="16"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0, 0, 10, 0"
|
||||
Foreground="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Visibility="{Binding ElementName=_this, Path=ShowingNotificationCount, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Text="{Binding ElementName=_this, Path=NotificationCount, Mode=OneWay}" />
|
||||
<buttons:MenuButton FontSize="16"
|
||||
Height="30"
|
||||
Title="Notifications"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="0, 0, 0, 1"
|
||||
Clicked="NotificationsButton_Clicked"/>
|
||||
</Grid>
|
||||
<local:ExpandableMenuSection
|
||||
SectionTitle="Trade" Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16">
|
||||
<local:ExpandableMenuSection.Children>
|
||||
<buttons:MenuButton Title="Alerts"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="TradeAlertsButton_Clicked">
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Kamadan"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
@@ -83,8 +117,15 @@
|
||||
Cursor="Hand"
|
||||
Clicked="ToolboxButton_Clicked">
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="DSOAL"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="DSOALButton_Clicked">
|
||||
</buttons:MenuButton>
|
||||
</local:ExpandableMenuSection.Children>
|
||||
</local:ExpandableMenuSection>
|
||||
</local:ExpandableMenuSection>
|
||||
<local:ExpandableMenuSection
|
||||
SectionTitle="Settings" Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16">
|
||||
@@ -134,5 +175,5 @@
|
||||
</local:ExpandableMenuSection.Children>
|
||||
</local:ExpandableMenuSection>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Notifications;
|
||||
using Daybreak.Views;
|
||||
using Daybreak.Views.Copy;
|
||||
using Daybreak.Views.Onboarding.DSOAL;
|
||||
using Daybreak.Views.Onboarding.Toolbox;
|
||||
using Daybreak.Views.Onboarding.UMod;
|
||||
using Daybreak.Views.Trade;
|
||||
@@ -9,7 +12,11 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
@@ -19,11 +26,20 @@ namespace Daybreak.Controls;
|
||||
public partial class MenuList : UserControl
|
||||
{
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly INotificationStorage notificationStorage;
|
||||
private readonly ILiveOptions<LauncherOptions> liveOptions;
|
||||
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool showingNotificationCount;
|
||||
[GenerateDependencyProperty]
|
||||
private int notificationCount;
|
||||
|
||||
public MenuList()
|
||||
: this(
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<INotificationStorage>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<LauncherOptions>>())
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -31,9 +47,11 @@ public partial class MenuList : UserControl
|
||||
|
||||
private MenuList(
|
||||
IViewManager viewManager,
|
||||
INotificationStorage notificationStorage,
|
||||
ILiveOptions<LauncherOptions> liveOptions)
|
||||
{
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.notificationStorage = notificationStorage.ThrowIfNull();
|
||||
this.liveOptions = liveOptions.ThrowIfNull();
|
||||
}
|
||||
|
||||
@@ -77,6 +95,11 @@ public partial class MenuList : UserControl
|
||||
this.viewManager.ShowView<GuildwarsDownloadView>();
|
||||
}
|
||||
|
||||
private void CopyGuildwarsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<GuildwarsCopySelectionView>();
|
||||
}
|
||||
|
||||
private void UModButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<UModOnboardingEntryView>();
|
||||
@@ -87,6 +110,11 @@ public partial class MenuList : UserControl
|
||||
this.viewManager.ShowView<ToolboxOnboardingEntryView>();
|
||||
}
|
||||
|
||||
private void DSOALButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<DSOALOnboardingEntryView>();
|
||||
}
|
||||
|
||||
private void KamadanButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<KamadanTradeChatView>();
|
||||
@@ -101,4 +129,52 @@ public partial class MenuList : UserControl
|
||||
{
|
||||
this.viewManager.ShowView<PriceQuotesView>();
|
||||
}
|
||||
|
||||
private void NotificationsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<NotificationsView>();
|
||||
}
|
||||
|
||||
private void TradeAlertsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<TradeAlertsView>();
|
||||
}
|
||||
|
||||
private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
this.cancellationTokenSource = new CancellationTokenSource();
|
||||
this.PeriodicallyCheckUnopenedNotifications(this.cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
private void UserControl_Unloaded(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
this.cancellationTokenSource?.Dispose();
|
||||
this.cancellationTokenSource = default;
|
||||
}
|
||||
|
||||
private async void PeriodicallyCheckUnopenedNotifications(CancellationToken cancellationToken)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var unopenedNotifications = this.notificationStorage.GetPendingNotifications().ToList();
|
||||
if (unopenedNotifications.Any())
|
||||
{
|
||||
await this.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
this.ShowingNotificationCount = true;
|
||||
this.NotificationCount = unopenedNotifications.Count;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await this.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
this.ShowingNotificationCount = false;
|
||||
});
|
||||
}
|
||||
|
||||
await Task.Delay(5000, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Minimap"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
@@ -79,7 +78,9 @@
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Clicked="MaximizeButton_Clicked"></buttons:MaximizeButton>
|
||||
</Grid>
|
||||
<WrapPanel Background="{DynamicResource Daybreak.Brushes.Background}" VerticalAlignment="Top" HorizontalAlignment="Right" >
|
||||
<WrapPanel Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Right" >
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=TargetEntityId, Mode=OneWay}" Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16" Padding="5" ></TextBlock>
|
||||
<TextBlock Text=" - " Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
|
||||
@@ -23,8 +23,6 @@ using Daybreak.Services.Themes;
|
||||
using Daybreak.Services.Metrics;
|
||||
using System.Diagnostics.Metrics;
|
||||
using System.Diagnostics;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.Views.Desktop;
|
||||
|
||||
namespace Daybreak.Controls.Minimap;
|
||||
|
||||
@@ -40,8 +38,6 @@ public partial class GuildwarsMinimap : UserControl
|
||||
private const int MapDownscaleFactor = 10;
|
||||
private const int EntitySize = 100;
|
||||
private const float PositionRadius = 150;
|
||||
// Minimum amount of milliseconds to pass between calculating paths to objectives
|
||||
private const int MinPathCalculationFrequency = 500;
|
||||
|
||||
private readonly Histogram<double> drawingLatency;
|
||||
private readonly DispatcherTimer dispatcherTimer = new(DispatcherPriority.Render);
|
||||
@@ -65,9 +61,10 @@ public partial class GuildwarsMinimap : UserControl
|
||||
private Point originPoint = new(0, 0);
|
||||
private Vector originOffset = new(0, 0);
|
||||
private Point initialClickPoint = new(0, 0);
|
||||
private Point lastPathfindingPoint = new(0, 0);
|
||||
private int pathfindingObjectiveCount = 0;
|
||||
private DebounceResponse? cachedDebounceResponse;
|
||||
private PathfindingCache? pathfindingCache;
|
||||
private SKSurface? entitySurface;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private PathingData pathingData = new();
|
||||
@@ -89,7 +86,7 @@ public partial class GuildwarsMinimap : UserControl
|
||||
public event EventHandler<LivingEntity>? LivingEntityClicked;
|
||||
public event EventHandler<PlayerInformation>? PlayerInformationClicked;
|
||||
public event EventHandler<MapIcon>? MapIconClicked;
|
||||
public event EventHandler<Profession?> ProfessionClicked;
|
||||
public event EventHandler<Profession>? ProfessionClicked;
|
||||
|
||||
public GuildwarsMinimap()
|
||||
:this(
|
||||
@@ -122,6 +119,11 @@ public partial class GuildwarsMinimap : UserControl
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (!this.IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Property == ActualHeightProperty ||
|
||||
e.Property == ActualWidthProperty)
|
||||
{
|
||||
@@ -131,6 +133,8 @@ public partial class GuildwarsMinimap : UserControl
|
||||
{
|
||||
this.guildwarsEntityDebouncer.ClearCaches();
|
||||
this.mainPlayerPositionHistory.Clear();
|
||||
this.lastPathfindingPoint = new Point(0, 0);
|
||||
this.pathfindingObjectiveCount = 0;
|
||||
this.UpdateGameData();
|
||||
this.DrawMap();
|
||||
}
|
||||
@@ -147,7 +151,8 @@ public partial class GuildwarsMinimap : UserControl
|
||||
|
||||
private void UpdateGameData()
|
||||
{
|
||||
if(this.GameData.Valid is false)
|
||||
if(this.GameData is null ||
|
||||
this.GameData.Valid is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -162,8 +167,8 @@ public partial class GuildwarsMinimap : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
this.TargetEntityId = this.GameData.Session?.CurrentTargetId ?? 0;
|
||||
this.TargetEntityModelId = (int?)this.GameData.LivingEntities?.FirstOrDefault(e => e.Id == this.TargetEntityId).ModelType ?? 0;
|
||||
this.TargetEntityId = this.GameData.CurrentTargetId ?? 0;
|
||||
this.TargetEntityModelId = (int?)this.GameData.LivingEntities?.FirstOrDefault(e => e.Id == this.TargetEntityId)?.ModelType ?? 0;
|
||||
var screenVirtualWidth = this.ActualWidth / this.Zoom;
|
||||
var screenVirtualHeight = this.ActualHeight / this.Zoom;
|
||||
var position = debounceResponse.MainPlayer.Position!.Value;
|
||||
@@ -203,7 +208,8 @@ public partial class GuildwarsMinimap : UserControl
|
||||
|
||||
private void DrawMap()
|
||||
{
|
||||
if (this.PathingData.Trapezoids is null)
|
||||
if (this.PathingData is null ||
|
||||
this.PathingData.Trapezoids is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -297,6 +303,7 @@ public partial class GuildwarsMinimap : UserControl
|
||||
|
||||
this.CalculatePathsToObjectives();
|
||||
|
||||
var foregroundColor = this.FindResource("MahApps.Colors.ThemeBackground").Cast<Color>();
|
||||
bitmap.Clear(Colors.Transparent);
|
||||
using var context = bitmap.GetBitmapContext();
|
||||
var sw = Stopwatch.StartNew();
|
||||
@@ -307,7 +314,8 @@ public partial class GuildwarsMinimap : UserControl
|
||||
this.originPoint,
|
||||
this.Zoom,
|
||||
PositionRadius,
|
||||
EntitySize);
|
||||
EntitySize,
|
||||
foregroundColor);
|
||||
this.drawingService.DrawEngagementArea(bitmap, this.cachedDebounceResponse ?? new DebounceResponse());
|
||||
this.drawingService.DrawMainPlayerPositionHistory(bitmap, this.mainPlayerPositionHistory);
|
||||
this.drawingService.DrawPaths(bitmap, this.pathfindingCache);
|
||||
@@ -373,16 +381,30 @@ public partial class GuildwarsMinimap : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
var playerPosition = new Point
|
||||
{
|
||||
X = this.cachedDebounceResponse?.MainPlayer.Position?.X ?? 0,
|
||||
Y = this.cachedDebounceResponse?.MainPlayer.Position?.Y ?? 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* If we already calculated paths for the current objectives, return early.
|
||||
*/
|
||||
if (currentMapQuests.Count == this.pathfindingObjectiveCount &&
|
||||
(playerPosition - this.lastPathfindingPoint).Length < PositionRadius + PositionRadius)
|
||||
{
|
||||
this.calculatingPathToObjectives = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.pathfindingObjectiveCount = currentMapQuests.Count;
|
||||
this.lastPathfindingPoint = playerPosition;
|
||||
var pathfindingTasks = currentMapQuests
|
||||
.Select(questMetaData =>
|
||||
{
|
||||
return this.pathfinder.CalculatePath(
|
||||
this.PathingData,
|
||||
new Point
|
||||
{
|
||||
X = this.cachedDebounceResponse?.MainPlayer.Position?.X ?? 0,
|
||||
Y = this.cachedDebounceResponse?.MainPlayer.Position?.Y ?? 0,
|
||||
},
|
||||
playerPosition,
|
||||
new Point
|
||||
{
|
||||
X = questMetaData.Position!.Value.X,
|
||||
@@ -392,7 +414,7 @@ public partial class GuildwarsMinimap : UserControl
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.WhenAll(pathfindingTasks.Append(Task.Delay(MinPathCalculationFrequency)));
|
||||
await Task.WhenAll(pathfindingTasks);
|
||||
var paths = new List<PathfindingResponse>();
|
||||
var colors = new List<Color>();
|
||||
for(var i = 0; i < currentMapQuests.Count; i++)
|
||||
@@ -401,7 +423,7 @@ public partial class GuildwarsMinimap : UserControl
|
||||
var result = await pathfindingTasks[i];
|
||||
if (result.TryExtractSuccess(out var pathfindingResponse))
|
||||
{
|
||||
paths.Add(pathfindingResponse);
|
||||
paths.Add(pathfindingResponse!);
|
||||
var questColor = GetQuestColor(quest);
|
||||
var pathColor = Color.FromArgb(100, questColor.R, questColor.G, questColor.B);
|
||||
colors.Add(pathColor);
|
||||
@@ -567,23 +589,26 @@ public partial class GuildwarsMinimap : UserControl
|
||||
|
||||
private void GuildwarsMinimap_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (this.GameData.Valid is false)
|
||||
if (this.GameData.Valid is false ||
|
||||
this.GameData.MainPlayer is null ||
|
||||
this.GameData.Party is null ||
|
||||
this.GameData.WorldPlayers is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.DragMinimap();
|
||||
if (this.CheckMouseOverEntity(this.GameData.Party!.OfType<IEntity>()) is not null)
|
||||
if (this.CheckMouseOverEntity(this.GameData.Party.OfType<IEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.WorldPlayers!.OfType<IEntity>()) is not null)
|
||||
if (this.CheckMouseOverEntity(this.GameData.WorldPlayers.OfType<IEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(Enumerable.Repeat(this.GameData.MainPlayer.As<IEntity>(), 1)) is not null)
|
||||
if (this.CheckMouseOverEntity(Enumerable.Repeat(this.GameData.MainPlayer.Cast<IEntity>(), 1)) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -598,14 +623,14 @@ public partial class GuildwarsMinimap : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.MainPlayer!.Value.QuestLog!
|
||||
if (this.CheckMouseOverEntity(this.GameData.MainPlayer.QuestLog!
|
||||
.Where(entity => this.drawingService.IsEntityOnScreen(entity.Position, out _, out _))
|
||||
.OfType<IPositionalEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.MainPlayer!.Value.QuestLog!
|
||||
if (this.CheckMouseOverEntity(this.GameData.MainPlayer.QuestLog!
|
||||
.Where(entity => !this.drawingService.IsEntityOnScreen(entity.Position, out _, out _))
|
||||
.Select(oldQuestMetadata =>
|
||||
{
|
||||
@@ -650,32 +675,32 @@ public partial class GuildwarsMinimap : UserControl
|
||||
|
||||
private void QuestContextMenu_QuestContextMenuClicked(object _, QuestMetadata? quest)
|
||||
{
|
||||
if (quest is not QuestMetadata)
|
||||
if (quest is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.QuestMetadataClicked?.Invoke(this, quest.Value);
|
||||
this.QuestMetadataClicked?.Invoke(this, quest);
|
||||
}
|
||||
|
||||
private void PlayerContextMenu_PlayerContextMenuClicked(object _, PlayerInformation? playerInformation)
|
||||
{
|
||||
if (playerInformation is not PlayerInformation)
|
||||
if (playerInformation is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.PlayerInformationClicked?.Invoke(this, playerInformation.Value);
|
||||
this.PlayerInformationClicked?.Invoke(this, playerInformation);
|
||||
}
|
||||
|
||||
private void LivingEntityContextMenu_LivingEntityContextMenuClicked(object _, LivingEntity? livingEntity)
|
||||
{
|
||||
if (livingEntity is not LivingEntity)
|
||||
if (livingEntity is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.LivingEntityClicked?.Invoke(this, livingEntity.Value);
|
||||
this.LivingEntityClicked?.Invoke(this, livingEntity);
|
||||
}
|
||||
|
||||
private void LivingEntityContextMenu_LivingEntityProfessionContextMenuClicked(object _, Profession? e)
|
||||
@@ -690,12 +715,12 @@ public partial class GuildwarsMinimap : UserControl
|
||||
|
||||
private void MapIconContextMenu_MapIconContextMenuClicked(object _, MapIcon? mapIcon)
|
||||
{
|
||||
if (mapIcon is not MapIcon)
|
||||
if (mapIcon is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.MapIconClicked?.Invoke(this, mapIcon.Value);
|
||||
this.MapIconClicked?.Invoke(this, mapIcon);
|
||||
}
|
||||
|
||||
private void MaximizeButton_Clicked(object sender, EventArgs e)
|
||||
@@ -707,21 +732,6 @@ public partial class GuildwarsMinimap : UserControl
|
||||
}
|
||||
}
|
||||
|
||||
private void VerifySurface()
|
||||
{
|
||||
var peekPixels = this.entitySurface?.PeekPixels();
|
||||
if (!this.resizeEntities &&
|
||||
this.ActualWidth == peekPixels?.Width &&
|
||||
this.ActualHeight == peekPixels?.Height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var imageInfo = new SKImageInfo((int)this.ActualWidth, (int)this.ActualHeight, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
var surface = SKSurface.Create(imageInfo);
|
||||
this.entitySurface = surface;
|
||||
}
|
||||
|
||||
private static bool PositionsCollide(Position position1, Position position2)
|
||||
{
|
||||
var a = PositionRadius + PositionRadius;
|
||||
|
||||
@@ -38,14 +38,18 @@
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.Accent}"
|
||||
HorizontalAlignment="Right"
|
||||
Expired="NotificationView_Expired"/>
|
||||
MaxHeight="300"
|
||||
Expired="NotificationView_Expired"
|
||||
Closed="NotificationView_Closed"/>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="ErrorNotificationDataTemplate">
|
||||
<local:NotificationView
|
||||
Background="{DynamicResource Daybreak.Brushes.Background}"
|
||||
Foreground="{DynamicResource MahApps.Brushes.Accent}"
|
||||
HorizontalAlignment="Right"
|
||||
Expired="NotificationView_Expired"/>
|
||||
MaxHeight="300"
|
||||
Expired="NotificationView_Expired"
|
||||
Closed="NotificationView_Closed"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.Resources>
|
||||
</ItemsControl>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Daybreak.Models.Notifications;
|
||||
using Daybreak.Services.Notifications;
|
||||
using Daybreak.Services.Sounds;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Core.Extensions;
|
||||
@@ -17,6 +19,7 @@ public partial class NotificationStackpanel : UserControl
|
||||
{
|
||||
private static readonly TimeSpan ProcInterval = TimeSpan.FromSeconds(1);
|
||||
|
||||
private readonly ISoundService soundService;
|
||||
private readonly INotificationProducer notificationProducer;
|
||||
private readonly DispatcherTimer dispatcherTimer = new();
|
||||
private CancellationTokenSource? cancellationToken;
|
||||
@@ -24,13 +27,16 @@ public partial class NotificationStackpanel : UserControl
|
||||
public ObservableCollection<NotificationWrapper> Notifications { get; } = new();
|
||||
|
||||
public NotificationStackpanel() :
|
||||
this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<INotificationProducer>())
|
||||
this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<INotificationProducer>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ISoundService>())
|
||||
{
|
||||
}
|
||||
|
||||
public NotificationStackpanel(
|
||||
INotificationProducer notificationProducer)
|
||||
internal NotificationStackpanel(
|
||||
INotificationProducer notificationProducer,
|
||||
ISoundService soundService)
|
||||
{
|
||||
this.soundService = soundService.ThrowIfNull();
|
||||
this.notificationProducer = notificationProducer.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
|
||||
@@ -58,6 +64,21 @@ public partial class NotificationStackpanel : UserControl
|
||||
}
|
||||
|
||||
this.Notifications.Remove(notificationWrapper);
|
||||
notificationWrapper.Notification!.Closed = true;
|
||||
this.soundService.PlayNotifyClose();
|
||||
}
|
||||
|
||||
private void NotificationView_Closed(object sender, EventArgs e)
|
||||
{
|
||||
if (sender.As<UserControl>()?.DataContext is not NotificationWrapper notificationWrapper)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.Notifications.Remove(notificationWrapper);
|
||||
this.notificationProducer.OpenNotification(notificationWrapper.Notification!);
|
||||
notificationWrapper.Notification!.Closed = true;
|
||||
this.soundService.PlayNotifyClose();
|
||||
}
|
||||
|
||||
private async void ConsumeNotifications()
|
||||
@@ -66,6 +87,21 @@ public partial class NotificationStackpanel : UserControl
|
||||
await foreach(var notification in this.notificationProducer.Consume(this.cancellationToken.Token))
|
||||
{
|
||||
this.Notifications.Insert(0, new NotificationWrapper { Notification = notification, DispatcherTimer = this.dispatcherTimer });
|
||||
switch (notification.Level)
|
||||
{
|
||||
case LogLevel.Critical:
|
||||
case LogLevel.Warning:
|
||||
case LogLevel.Error:
|
||||
this.soundService.PlayNotifyError();
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
case LogLevel.Debug:
|
||||
case LogLevel.Trace:
|
||||
this.soundService.PlayNotifyInformation();
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Unexpected notification level {notification.Level}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Notifications.NotificationTemplate"
|
||||
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.Notifications"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:DateTimeConverter x:Key="DateTimeConverter" Format="f"></converters:DateTimeConverter>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></converters:BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Border
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
<buttons:HighlightButton
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<buttons:HighlightButton.ButtonContent>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="10" />
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="{Binding Title, Mode=OneWay}"
|
||||
FontSize="20"
|
||||
Grid.Row="0"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding CreationTime, Mode=OneWay, Converter={StaticResource DateTimeConverter}}"
|
||||
FontSize="12"
|
||||
Grid.Row="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0, 0, 5, 0"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding Description, Mode=OneWay}"
|
||||
FontSize="14"
|
||||
Grid.Row="2"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
TextWrapping="Wrap"/>
|
||||
<Rectangle Grid.RowSpan="3"
|
||||
Fill="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Visibility="{Binding Closed, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Opacity="0.3"/>
|
||||
</Grid>
|
||||
</buttons:HighlightButton.ButtonContent>
|
||||
</buttons:HighlightButton>
|
||||
<buttons:CancelButton Height="20"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Clicked="CancelButton_Clicked"></buttons:CancelButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,42 @@
|
||||
using Daybreak.Models.Notifications;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.Notifications;
|
||||
/// <summary>
|
||||
/// Interaction logic for NotificationTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class NotificationTemplate : UserControl
|
||||
{
|
||||
public event EventHandler<Notification>? OpenClicked;
|
||||
public event EventHandler<Notification>? RemoveClicked;
|
||||
|
||||
public NotificationTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is not Notification notification)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.OpenClicked?.Invoke(this, notification);
|
||||
|
||||
// Resetting the data context triggers the data bindings to update
|
||||
this.DataContext = default;
|
||||
this.DataContext = notification;
|
||||
}
|
||||
|
||||
private void CancelButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is not Notification notification)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.RemoveClicked?.Invoke(this, notification);
|
||||
}
|
||||
}
|
||||
@@ -13,34 +13,47 @@
|
||||
MinHeight="50"
|
||||
Width="300"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<buttons:HighlightButton
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<buttons:HighlightButton
|
||||
HighlightColor="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Background="{Binding ElementName=_this, Path=Background, Mode=OneWay}"
|
||||
Width="{Binding ElementName=_this, Path=Width, Mode=OneTime}"
|
||||
Clicked="HighlightButton_Clicked">
|
||||
<buttons:HighlightButton.ButtonContent>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Border
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Grid.RowSpan="2"/>
|
||||
<TextBlock Text="{Binding Notification.Title}"
|
||||
<buttons:HighlightButton.ButtonContent>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Border
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Grid.RowSpan="2" />
|
||||
<TextBlock Text="{Binding Title, Mode=OneWay}"
|
||||
Grid.Row="0"
|
||||
FontSize="18"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0, 0, 0, 10"/>
|
||||
<TextBlock Text="{Binding Notification.Description}"
|
||||
Margin="5, 0, 5, 10" />
|
||||
<TextBlock Text="{Binding Description, Mode=OneWay}"
|
||||
Margin="5, 0, 5, 0"
|
||||
Grid.Row="1"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Left"
|
||||
TextWrapping="Wrap"/>
|
||||
</Grid>
|
||||
</buttons:HighlightButton.ButtonContent>
|
||||
</buttons:HighlightButton>
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</buttons:HighlightButton.ButtonContent>
|
||||
</buttons:HighlightButton>
|
||||
<buttons:CancelButton Height="15"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Margin="5"
|
||||
Visibility="{Binding ElementName=_this, Path=Dismissible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Clicked="CancelButton_Clicked"></buttons:CancelButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Threading;
|
||||
@@ -16,9 +17,14 @@ public partial class NotificationView : UserControl
|
||||
private static readonly TimeSpan ExpirationDuration = TimeSpan.FromSeconds(5);
|
||||
|
||||
public event EventHandler? Expired;
|
||||
public event EventHandler? Closed;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool dismissible;
|
||||
|
||||
private DispatcherTimer? dispatcherTimer;
|
||||
private DateTime notificationExpirationTime = DateTime.Now;
|
||||
private DateTime showNotificationExpirationTime = DateTime.Now; // The default notification timeout. Can be extended by moving the mouse over the notification
|
||||
private DateTime requestedNotificationExpirationTime = DateTime.Now; // Some notifications can have their desired timeouts. Don't make the notification disappear before this time
|
||||
|
||||
public NotificationView()
|
||||
{
|
||||
@@ -33,7 +39,8 @@ public partial class NotificationView : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
this.notificationExpirationTime = DateTime.Now + ExpirationDuration;
|
||||
this.showNotificationExpirationTime = DateTime.Now + ExpirationDuration;
|
||||
this.requestedNotificationExpirationTime = notificationWrapper.Notification?.ExpirationTime ?? DateTime.Now;
|
||||
if (this.dispatcherTimer is not null)
|
||||
{
|
||||
this.dispatcherTimer.Tick -= this.DispatcherTimer_Tick;
|
||||
@@ -42,6 +49,7 @@ public partial class NotificationView : UserControl
|
||||
this.dispatcherTimer = notificationWrapper.DispatcherTimer;
|
||||
notificationWrapper.DispatcherTimer.Tick += this.DispatcherTimer_Tick;
|
||||
this.SlideInAnimation();
|
||||
this.Dismissible = notificationWrapper.Notification?.Dismissible ?? false;
|
||||
}
|
||||
|
||||
private void UserControl_Unloaded(object _, RoutedEventArgs __)
|
||||
@@ -56,13 +64,18 @@ public partial class NotificationView : UserControl
|
||||
|
||||
private void UserControl_PreviewMouseMove(object _, MouseEventArgs __)
|
||||
{
|
||||
this.notificationExpirationTime = DateTime.Now + ExpirationDuration;
|
||||
this.showNotificationExpirationTime = DateTime.Now + ExpirationDuration;
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is not NotificationWrapper notificationWrapper ||
|
||||
notificationWrapper.Notification is not INotification notification)
|
||||
notificationWrapper.Notification is not ICancellableNotification notification)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!notification.Dismissible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -72,24 +85,61 @@ public partial class NotificationView : UserControl
|
||||
this.dispatcherTimer.Tick -= this.DispatcherTimer_Tick;
|
||||
}
|
||||
|
||||
this.SlideOutAnimation();
|
||||
notification?.OnClick?.Invoke();
|
||||
this.SlideOutAnimation(this.Closed);
|
||||
}
|
||||
|
||||
private void DispatcherTimer_Tick(object? sender, EventArgs __)
|
||||
private void CancelButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (DateTime.Now < this.notificationExpirationTime)
|
||||
if (this.DataContext is not NotificationWrapper notificationWrapper ||
|
||||
notificationWrapper.Notification is not ICancellableNotification notification)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!notification.Dismissible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dispatcherTimer is not null)
|
||||
{
|
||||
this.dispatcherTimer.Tick -= this.DispatcherTimer_Tick;
|
||||
}
|
||||
|
||||
this.SlideOutAnimation(this.Expired);
|
||||
}
|
||||
|
||||
private void DispatcherTimer_Tick(object? sender, EventArgs __)
|
||||
{
|
||||
if (sender is not DispatcherTimer senderDispatcherTimer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.DataContext is not NotificationWrapper notificationWrapper ||
|
||||
notificationWrapper.Notification is not ICancellableNotification notification)
|
||||
{
|
||||
senderDispatcherTimer.Tick -= this.DispatcherTimer_Tick;
|
||||
this.SlideOutAnimation(this.Closed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (notification.CancellationRequested)
|
||||
{
|
||||
senderDispatcherTimer.Tick -= this.DispatcherTimer_Tick;
|
||||
this.SlideOutAnimation(this.Closed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DateTime.Now < this.showNotificationExpirationTime ||
|
||||
DateTime.Now < this.requestedNotificationExpirationTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
senderDispatcherTimer.Tick -= this.DispatcherTimer_Tick;
|
||||
this.SlideOutAnimation();
|
||||
this.SlideOutAnimation(this.Expired);
|
||||
}
|
||||
|
||||
private void SlideInAnimation()
|
||||
@@ -106,7 +156,7 @@ public partial class NotificationView : UserControl
|
||||
this.BeginAnimation(WidthProperty, doubleAnimation);
|
||||
}
|
||||
|
||||
private void SlideOutAnimation()
|
||||
private void SlideOutAnimation(EventHandler? onCompleted)
|
||||
{
|
||||
var doubleAnimation = new DoubleAnimation
|
||||
{
|
||||
@@ -119,7 +169,7 @@ public partial class NotificationView : UserControl
|
||||
|
||||
doubleAnimation.Completed += (_, e) =>
|
||||
{
|
||||
this.Expired?.Invoke(this, e);
|
||||
onCompleted?.Invoke(this, e);
|
||||
};
|
||||
this.BeginAnimation(WidthProperty, doubleAnimation);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ public partial class PlayerContextMenu : UserControl
|
||||
|
||||
private void TextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.PlayerContextMenuClicked?.Invoke(this, this.DataContext as PlayerInformation? ?? default);
|
||||
this.PlayerContextMenuClicked?.Invoke(this, this.DataContext as PlayerInformation ?? default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ public partial class QuestContextMenu : UserControl
|
||||
|
||||
private void TextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.QuestContextMenuClicked?.Invoke(this, this.DataContext as QuestMetadata? ?? default);
|
||||
this.QuestContextMenuClicked?.Invoke(this, this.DataContext as QuestMetadata ?? default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<TextBox Foreground="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=Foreground, Mode=OneWay}"
|
||||
<TextBox x:Name="TextBox"
|
||||
Foreground="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=Foreground, Mode=OneWay}"
|
||||
FontSize="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=FontSize, Mode=OneWay}"
|
||||
FontFamily="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=FontFamily, Mode=OneWay}"
|
||||
FontStretch="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=FontStretch, Mode=OneWay}"
|
||||
|
||||
@@ -37,6 +37,11 @@ public partial class SearchTextBox : UserControl
|
||||
this.dispatcherTimer.Tick += this.DispatcherTimer_Tick;
|
||||
}
|
||||
|
||||
public void FocusOnTextBox()
|
||||
{
|
||||
this.TextBox.Focus();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Templates.BagContentTemplate"
|
||||
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.Templates"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
xmlns:controls="clr-namespace:Daybreak.Controls"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
DataContextChanged="UserControl_DataContextChanged"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="0, 0, 1, 1"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
Height="30">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
<converters:BooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" TriggerValue="True"></converters:BooleanToVisibilityConverter>
|
||||
<ContextMenu x:Key="BagItemContextMenu">
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<controls:BagItemContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
WikiClicked="BagItemContextMenu_WikiClicked"
|
||||
PriceHistoryClicked="BagItemContextMenu_PriceHistoryClicked"/>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
</UserControl.Resources>
|
||||
<Grid
|
||||
Visibility="{Binding ElementName=_this, Path=ContentVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<Image Source="{Binding ElementName=_this, Path=ImageSource, Mode=OneWay}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Height="30"
|
||||
Width="30"
|
||||
Visibility="{Binding ElementName=_this, Path=IconVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Cursor="Hand"/>
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=ItemId, Mode=OneWay}"
|
||||
FontSize="20"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Visibility="{Binding ElementName=_this, Path=IconVisible, Mode=OneWay, Converter={StaticResource InverseBooleanToVisibilityConverter}}"/>
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=Count, Mode=OneWay}"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="5"/>
|
||||
<buttons:HighlightButton
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
MouseRightButtonDown="HighlightButton_MouseRightButtonDown"
|
||||
MouseLeftButtonDown="HighlightButton_MouseLeftButtonDown"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,181 @@
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Images;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using static Daybreak.Models.Guildwars.ItemBase;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for BagContentTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class BagContentTemplate : UserControl
|
||||
{
|
||||
private readonly IImageCache imageCache;
|
||||
private readonly IIconCache iconCache;
|
||||
|
||||
private IBagContent? cachedBagContent;
|
||||
private string? cachedIconUri = default!;
|
||||
|
||||
public event EventHandler<IBagContent>? ItemClicked;
|
||||
public event EventHandler<ItemBase>? ItemWikiClicked;
|
||||
public event EventHandler<ItemBase>? PriceHistoryClicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private ImageSource imageSource = default!;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool iconVisible;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private bool contentVisible;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private int itemId;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private int count;
|
||||
|
||||
public BagContentTemplate()
|
||||
: this(
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IImageCache>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IIconCache>())
|
||||
{
|
||||
}
|
||||
|
||||
public BagContentTemplate(
|
||||
IImageCache imageCache,
|
||||
IIconCache iconCache)
|
||||
{
|
||||
this.imageCache = imageCache.ThrowIfNull();
|
||||
this.iconCache = iconCache.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not BagItem bagItem ||
|
||||
bagItem.Item is Unknown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var itemContextMenu = this.FindResource("BagItemContextMenu");
|
||||
if (itemContextMenu is not ContextMenu bagItemContextMenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ContextMenu = bagItemContextMenu;
|
||||
this.ContextMenu.DataContext = bagItem;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
}
|
||||
|
||||
private void HighlightButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not IBagContent bagContent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ItemClicked?.Invoke(this, bagContent);
|
||||
}
|
||||
|
||||
private void BagItemContextMenu_WikiClicked(object _, ItemBase e)
|
||||
{
|
||||
this.ItemWikiClicked?.Invoke(this, e);
|
||||
this.ContextMenu.IsOpen = false;
|
||||
}
|
||||
|
||||
private void BagItemContextMenu_PriceHistoryClicked(object _, ItemBase e)
|
||||
{
|
||||
this.PriceHistoryClicked?.Invoke(this, e);
|
||||
this.ContextMenu.IsOpen = false;
|
||||
}
|
||||
|
||||
private async void UserControl_DataContextChanged(object _, DependencyPropertyChangedEventArgs __)
|
||||
{
|
||||
if (this.DataContext is not IBagContent bagContent)
|
||||
{
|
||||
this.cachedBagContent = default;
|
||||
this.ContentVisible = false;
|
||||
this.ImageSource = default;
|
||||
this.cachedIconUri = default;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.BagContentAlreadyLoaded(bagContent))
|
||||
{
|
||||
this.ContentVisible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bagContent is not BagItem bagItem)
|
||||
{
|
||||
if (bagContent is UnknownBagItem unknownBagItem)
|
||||
{
|
||||
this.cachedBagContent = unknownBagItem;
|
||||
this.ContentVisible = true;
|
||||
this.IconVisible = false;
|
||||
this.ItemId = (int)unknownBagItem.ItemId;
|
||||
this.Count = (int)unknownBagItem.Count;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.cachedBagContent = bagItem;
|
||||
this.ContentVisible = true;
|
||||
this.ItemId = bagItem.Item.Id;
|
||||
this.Count = (int)bagItem.Count;
|
||||
var maybeIconUri = await this.iconCache.GetIconUri(bagItem.Item);
|
||||
if (maybeIconUri is not string iconUri ||
|
||||
this.cachedIconUri == iconUri)
|
||||
{
|
||||
this.IconVisible = this.cachedIconUri == maybeIconUri;
|
||||
return;
|
||||
}
|
||||
|
||||
this.IconVisible = true;
|
||||
this.cachedIconUri = iconUri;
|
||||
await this.Dispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
this.ImageSource = await this.imageCache.GetImage(iconUri).ConfigureAwait(true);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private bool BagContentAlreadyLoaded(IBagContent bagContent)
|
||||
{
|
||||
if (this.cachedBagContent is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bagContent is BagItem newBagItem &&
|
||||
this.cachedBagContent is BagItem oldBagItem)
|
||||
{
|
||||
return newBagItem.Slot == oldBagItem.Slot &&
|
||||
newBagItem.Count == oldBagItem.Count &&
|
||||
newBagItem.Item == oldBagItem.Item;
|
||||
}
|
||||
|
||||
if (bagContent is UnknownBagItem newUnknownBagItem &&
|
||||
this.cachedBagContent is UnknownBagItem oldUnknownBagItem)
|
||||
{
|
||||
return newUnknownBagItem.ItemId == oldUnknownBagItem.ItemId &&
|
||||
newUnknownBagItem.Count == oldUnknownBagItem.Count &&
|
||||
newUnknownBagItem.Slot == oldUnknownBagItem.Slot;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Templates.BagItemMenu"
|
||||
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.Templates"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
DataContextChanged="UserControl_DataContextChanged"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="{Binding Item.Name}"
|
||||
FontSize="16"
|
||||
Grid.Row="0"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Center"/>
|
||||
<WrapPanel HorizontalAlignment="Center"
|
||||
Grid.Row="1">
|
||||
<TextBlock Text="Id: "
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<Grid>
|
||||
<TextBlock Text="{Binding Item.Id}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding ItemId}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
</Grid>
|
||||
</WrapPanel>
|
||||
<WrapPanel HorizontalAlignment="Center"
|
||||
Grid.Row="2">
|
||||
<TextBlock Text="Wiki Url: "
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding Item.WikiUrl}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonDown="WikiTextBlock_MouseLeftButtonDown"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel HorizontalAlignment="Center"
|
||||
Grid.Row="3">
|
||||
<TextBlock Text="Modifiers Hash: "
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBox Text="{Binding ElementName=_this, Path=ModHash, Mode=OneWay}"
|
||||
FontSize="10"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
IsReadOnly="True"
|
||||
BorderThickness="0"
|
||||
Background="Transparent"/>
|
||||
</WrapPanel>
|
||||
<TextBlock Text="Modifiers"
|
||||
FontSize="16"
|
||||
Grid.Row="4"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
HorizontalAlignment="Center"/>
|
||||
<ScrollViewer
|
||||
Grid.Row="5">
|
||||
<ItemsControl ItemsSource="{Binding Modifiers, Mode=OneWay}"
|
||||
VirtualizingPanel.IsVirtualizing="True"
|
||||
VirtualizingPanel.IsContainerVirtualizable="True"
|
||||
VirtualizingPanel.VirtualizationMode="Recycling">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<WrapPanel
|
||||
Grid.Row="0">
|
||||
<TextBlock Text="Identifier: "
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding Identifier}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel
|
||||
Grid.Row="1">
|
||||
<TextBlock Text="Argument1: "
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding Argument1}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel
|
||||
Grid.Row="2">
|
||||
<TextBlock Text="Argument2: "
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding Argument2}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel
|
||||
Grid.Row="3">
|
||||
<TextBlock Text="Packed value: "
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<TextBlock Text="{Binding Modifier}"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
|
||||
</WrapPanel>
|
||||
<Border BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="0, 0, 0, 1"
|
||||
Grid.Row="4"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
<buttons:HighlightButton
|
||||
Grid.Row="6"
|
||||
Title="Close"
|
||||
FontSize="16"
|
||||
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
|
||||
Height="30"
|
||||
TextAlignment="Center"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
BorderBrush="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
Clicked="HighlightButton_Clicked"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,66 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.TradeChat;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
/// <summary>
|
||||
/// Interaction logic for BagItemMenu.xaml
|
||||
/// </summary>
|
||||
public partial class BagItemMenu : UserControl
|
||||
{
|
||||
private readonly IItemHashService itemHashService;
|
||||
|
||||
public event EventHandler? CloseClicked;
|
||||
public event EventHandler<ItemBase>? ItemWikiClicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string modHash = string.Empty;
|
||||
|
||||
public BagItemMenu()
|
||||
: this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IItemHashService>())
|
||||
{
|
||||
}
|
||||
|
||||
private BagItemMenu(
|
||||
IItemHashService itemHashService)
|
||||
{
|
||||
this.itemHashService = itemHashService.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void HighlightButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.CloseClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void UserControl_DataContextChanged(object _, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not IBagContent content)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ModHash = this.itemHashService.ComputeHash(content);
|
||||
}
|
||||
|
||||
private void WikiTextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.DataContext is not IBagContent content)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (content is not BagItem bagItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ItemWikiClicked?.Invoke(this, bagItem.Item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Templates.BagTemplate"
|
||||
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.Templates"
|
||||
DataContextChanged="UserControl_DataContextChanged"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="18"
|
||||
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Text="{Binding ElementName=_this, Path=BagName, Mode=OneWay}"
|
||||
Margin="10, 0, 0, 0"/>
|
||||
<Rectangle Fill="{DynamicResource MahApps.Brushes.ThemeForeground}"
|
||||
Height="1"/>
|
||||
<Grid x:Name="BagHolder" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,150 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for BagTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class BagTemplate : UserControl
|
||||
{
|
||||
private const int ItemsPerRow = 5;
|
||||
|
||||
public event EventHandler<ItemBase>? ItemWikiClicked;
|
||||
public event EventHandler<ItemBase>? PriceHistoryClicked;
|
||||
public event EventHandler<IBagContent>? ItemClicked;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string bagName = string.Empty;
|
||||
|
||||
public BagTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == DataContextProperty)
|
||||
{
|
||||
if (this.DataContext is not Bag bag ||
|
||||
bag.Capacity > 100)
|
||||
{
|
||||
this.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UserControl_DataContextChanged(object _, DependencyPropertyChangedEventArgs __)
|
||||
{
|
||||
if (this.DataContext is not Bag bag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.IsScreenVisible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bag.Capacity > 100)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.BagHolder.Children.Count != bag.Capacity)
|
||||
{
|
||||
this.SetupLayout(bag.Capacity);
|
||||
}
|
||||
|
||||
var distinctItems = bag.Items.DistinctBy(i => i.Slot).ToList();
|
||||
for (var i = 0; i < this.BagHolder.Children.Count; i++)
|
||||
{
|
||||
if (this.BagHolder.Children[i] is not BagContentTemplate bagContentTemplate)
|
||||
{
|
||||
throw new InvalidOperationException($"Expected {this.BagName} to contain {nameof(BagContentTemplate)} at slot {i}");
|
||||
}
|
||||
|
||||
var maybeItem = distinctItems.FirstOrDefault(item => (int)item.Slot == i);
|
||||
bagContentTemplate.DataContext = maybeItem ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
private void BagContentTemplate_ItemWikiClicked(object? _, ItemBase e)
|
||||
{
|
||||
this.ItemWikiClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void BagContentTemplate_PriceHistoryClicked(object? _, ItemBase e)
|
||||
{
|
||||
this.PriceHistoryClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void BagContentTemplate_ItemClicked(object? _, IBagContent e)
|
||||
{
|
||||
this.ItemClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void SetupLayout(int bagItemsCount)
|
||||
{
|
||||
this.BagHolder.RowDefinitions.Clear();
|
||||
this.BagHolder.ColumnDefinitions.Clear();
|
||||
foreach(BagContentTemplate child in this.BagHolder.Children)
|
||||
{
|
||||
child.ItemWikiClicked -= this.BagContentTemplate_ItemWikiClicked;
|
||||
child.PriceHistoryClicked -= this.BagContentTemplate_PriceHistoryClicked;
|
||||
child.ItemClicked -= this.BagContentTemplate_ItemClicked;
|
||||
}
|
||||
|
||||
this.BagHolder.Children.Clear();
|
||||
var rows = Math.Ceiling((double)bagItemsCount / ItemsPerRow);
|
||||
for (var i = 0; i < ItemsPerRow; i++)
|
||||
{
|
||||
this.BagHolder.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||
}
|
||||
|
||||
for (var i = 0; i < rows; i++)
|
||||
{
|
||||
this.BagHolder.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
||||
}
|
||||
|
||||
for (var i = 0; i < bagItemsCount; i++)
|
||||
{
|
||||
var currentIndex = this.BagHolder.Children.Count;
|
||||
var bagContentTemplate = new BagContentTemplate();
|
||||
Grid.SetColumn(bagContentTemplate, currentIndex % ItemsPerRow);
|
||||
Grid.SetRow(bagContentTemplate, currentIndex / ItemsPerRow);
|
||||
bagContentTemplate.VerticalAlignment = VerticalAlignment.Stretch;
|
||||
bagContentTemplate.HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
bagContentTemplate.ItemWikiClicked += this.BagContentTemplate_ItemWikiClicked;
|
||||
bagContentTemplate.PriceHistoryClicked += this.BagContentTemplate_PriceHistoryClicked;
|
||||
bagContentTemplate.ItemClicked += this.BagContentTemplate_ItemClicked;
|
||||
this.BagHolder.Children.Add(bagContentTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsScreenVisible()
|
||||
{
|
||||
if (!this.IsVisible)
|
||||
return false;
|
||||
|
||||
var container = VisualTreeHelper.GetParent(this) as FrameworkElement;
|
||||
if (container is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var bounds = this.TransformToAncestor(container).TransformBounds(new Rect(0, 0, this.RenderSize.Width, this.RenderSize.Height));
|
||||
var size = new Rect(0, 0, container.ActualWidth, container.ActualHeight);
|
||||
return size.IntersectsWith(bounds);
|
||||
}
|
||||
}
|
||||
@@ -149,8 +149,22 @@
|
||||
<TextBlock Grid.Column="7" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Text="{Binding ElementName=_this, Path=BuildEntry.EigthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<local:ChromiumBrowserWrapper x:Name="SkillBrowser" ControlsEnabled="False" Width="0" AddressBarReadonly="True" CanNavigate="True"></local:ChromiumBrowserWrapper>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6"
|
||||
x:Name="SideHolder">
|
||||
<local:ChromiumBrowserWrapper x:Name="SkillBrowser"
|
||||
MaxWidth="0"
|
||||
ControlsEnabled="True"
|
||||
AddressBarReadonly="True"
|
||||
CanNavigate="True"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
CanDownloadBuild="True"
|
||||
BuildDecoded="SkillBrowser_BuildDecoded"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
PreventDispose="True"
|
||||
MaximizeClicked="SkillBrowser_MaximizeClicked" />
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<Grid x:Name="SkillListContainer">
|
||||
@@ -158,7 +172,8 @@
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<local:SearchTextBox FontSize="20"
|
||||
<local:SearchTextBox x:Name="SkillListSearchTextBox"
|
||||
FontSize="20"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Background="Transparent"
|
||||
SearchText="{Binding ElementName=_this, Path=SkillSearchText, Mode=TwoWay}"
|
||||
@@ -212,5 +227,10 @@
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Grid.RowSpan="6"
|
||||
Grid.ColumnSpan="2"
|
||||
Visibility="Hidden"
|
||||
x:Name="FullScreenHolder">
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -5,7 +5,9 @@ using Daybreak.Models;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Utils;
|
||||
using Daybreak.Views;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -19,6 +21,7 @@ using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
|
||||
@@ -32,13 +35,18 @@ public partial class BuildTemplate : UserControl
|
||||
private const string InfoNamePlaceholder = "[NAME]";
|
||||
private const string BaseAddress = $"https://wiki.guildwars.com/wiki/{InfoNamePlaceholder}";
|
||||
|
||||
private readonly IBuildTemplateManager buildTemplateManager;
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly IAttributePointCalculator? attributePointCalculator;
|
||||
private readonly CancellationTokenSource? cancellationTokenSource = new();
|
||||
|
||||
private bool browserMaximized = false;
|
||||
private bool showingSkillList = false;
|
||||
private bool replacingSecondaryProfession;
|
||||
private bool replacingPrimaryProfession;
|
||||
private IAttributePointCalculator? attributePointCalculator;
|
||||
|
||||
private SkillTemplate? selectingSkillTemplate;
|
||||
private List<Skill>? skillListCache;
|
||||
private CancellationTokenSource? cancellationTokenSource = new();
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private string skillSearchText = string.Empty;
|
||||
@@ -55,14 +63,20 @@ public partial class BuildTemplate : UserControl
|
||||
public ObservableCollection<Profession> SecondaryProfessions { get; } = new();
|
||||
|
||||
public BuildTemplate()
|
||||
: this(Launcher.Instance.ApplicationServiceProvider.GetService<IAttributePointCalculator>()!)
|
||||
: this(Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBuildTemplateManager>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IAttributePointCalculator>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BuildTemplate(
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
IViewManager viewManager,
|
||||
IAttributePointCalculator attributePointCalculator)
|
||||
{
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull();
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.attributePointCalculator = attributePointCalculator.ThrowIfNull();
|
||||
|
||||
this.InitializeComponent();
|
||||
@@ -72,6 +86,12 @@ public partial class BuildTemplate : UserControl
|
||||
this.DataContextChanged += this.BuildTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
public void BrowseToUrl(string url)
|
||||
{
|
||||
this.SkillBrowser.Address = url;
|
||||
this.ShowInfoBrowser();
|
||||
}
|
||||
|
||||
private void BuildTemplate_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
@@ -157,24 +177,28 @@ public partial class BuildTemplate : UserControl
|
||||
private void BrowseToInfo(string infoName)
|
||||
{
|
||||
var address = BaseAddress.Replace(InfoNamePlaceholder, infoName.Replace(" ", "_"));
|
||||
this.SkillBrowser.Address = address;
|
||||
this.ShowInfoBrowser();
|
||||
this.BrowseToUrl(address);
|
||||
}
|
||||
|
||||
private void ShowInfoBrowser()
|
||||
{
|
||||
if (this.SkillBrowser.BrowserSupported is true)
|
||||
if (!this.SkillBrowser.BrowserSupported ||
|
||||
this.browserMaximized)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.SkillBrowser.Width = 400;
|
||||
return;
|
||||
}
|
||||
|
||||
this.HideSkillListView();
|
||||
this.SkillBrowser.MaxWidth = 400;
|
||||
this.SkillBrowser.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideInfoBrowser()
|
||||
{
|
||||
if (this.SkillBrowser.BrowserSupported is true)
|
||||
{
|
||||
this.SkillBrowser.Width = 0;
|
||||
this.SkillBrowser.MaxWidth = 0;
|
||||
this.SkillBrowser.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +216,7 @@ public partial class BuildTemplate : UserControl
|
||||
}
|
||||
|
||||
this.AvailableSkills = this.skillListCache;
|
||||
this.SkillListSearchTextBox.FocusOnTextBox();
|
||||
}
|
||||
|
||||
private void HideSkillListView()
|
||||
@@ -403,4 +428,41 @@ public partial class BuildTemplate : UserControl
|
||||
|
||||
this.HideSkillListView();
|
||||
}
|
||||
|
||||
private void SkillBrowser_MaximizeClicked(object sender, EventArgs e)
|
||||
{
|
||||
this.browserMaximized = !this.browserMaximized;
|
||||
if (this.browserMaximized)
|
||||
{
|
||||
this.SideHolder.Children.Remove(this.SkillBrowser);
|
||||
this.FullScreenHolder.Children.Add(this.SkillBrowser);
|
||||
this.FullScreenHolder.Visibility = Visibility.Visible;
|
||||
this.SkillBrowser.MaxWidth = double.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.FullScreenHolder.Children.Remove(this.SkillBrowser);
|
||||
this.SideHolder.Children.Add(this.SkillBrowser);
|
||||
this.FullScreenHolder.Visibility = Visibility.Hidden;
|
||||
this.SkillBrowser.MaxWidth = 400;
|
||||
}
|
||||
|
||||
if (e is MouseButtonEventArgs mouseButtonEventArgs)
|
||||
{
|
||||
mouseButtonEventArgs.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void SkillBrowser_BuildDecoded(object _, DownloadedBuild e)
|
||||
{
|
||||
if (e is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var buildEntry = this.buildTemplateManager.CreateBuild();
|
||||
buildEntry.Build = e.Build;
|
||||
buildEntry.Name = e.PreferredName ?? buildEntry.Name;
|
||||
this.viewManager.ShowView<BuildTemplateView>(buildEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
@@ -59,7 +58,7 @@ public partial class SkillTemplate : UserControl
|
||||
if (skill != Skill.NoSkill)
|
||||
{
|
||||
var maybeUri = await this.iconRetriever.GetIconUri(skill).ConfigureAwait(true);
|
||||
this.ImageSource = this.imageCache.GetImage(maybeUri);
|
||||
this.ImageSource = await this.imageCache.GetImage(maybeUri).ConfigureAwait(true);
|
||||
}
|
||||
else if (this.ImageSource is not null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Templates.TradeChatMessageTemplate"
|
||||
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.Templates"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:DateTimeConverter x:Key="DateTimeConverter"></converters:DateTimeConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Border
|
||||
BorderBrush="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
Grid.RowSpan="4"></Border>
|
||||
<WrapPanel
|
||||
Margin="10, 10, 10, 0"
|
||||
Grid.Row="0">
|
||||
<TextBlock
|
||||
Text="Player name: "
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox
|
||||
Text="{Binding Sender, Mode=OneWay}"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
FontSize="16"
|
||||
TextWrapping="Wrap"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="False"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
<buttons:CopyButton Height="20" Width="20"
|
||||
Clicked="NameCopyButton_Clicked"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel
|
||||
Margin="10, 0, 10, 0"
|
||||
Grid.Row="1">
|
||||
<TextBlock
|
||||
Text="Message: "
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox
|
||||
Text="{Binding Message, Mode=OneWay}"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
FontSize="16"
|
||||
TextWrapping="Wrap"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="False"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
<buttons:CopyButton Height="20" Width="20"
|
||||
Clicked="MessageCopyButton_Clicked"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel
|
||||
Margin="10, 0, 10, 0"
|
||||
Grid.Row="2">
|
||||
<TextBlock
|
||||
Text="Posted at: "
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox
|
||||
Text="{Binding Timestamp, Mode=OneWay, Converter={StaticResource DateTimeConverter}}"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
FontSize="16"
|
||||
TextWrapping="Wrap"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="False"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
<buttons:CopyButton Height="20" Width="20"
|
||||
Clicked="TimestampCopyButton_Clicked"/>
|
||||
</WrapPanel>
|
||||
<buttons:HighlightButton
|
||||
Grid.Row="3"
|
||||
Title="Close"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Background="{StaticResource Daybreak.Brushes.Background}"
|
||||
FontSize="16"
|
||||
HighlightColor="{StaticResource MahApps.Brushes.Accent}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
BorderBrush="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
TextPadding="5"
|
||||
Margin="10"
|
||||
Clicked="CloseButton_Clicked"></buttons:HighlightButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,56 @@
|
||||
using Daybreak.Models.Trade;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for TradeChatMessageTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class TradeChatMessageTemplate : UserControl
|
||||
{
|
||||
public event EventHandler<TraderMessage>? NameCopyClicked;
|
||||
public event EventHandler<TraderMessage>? MessageCopyClicked;
|
||||
public event EventHandler<TraderMessage>? TimestampCopyClicked;
|
||||
public event EventHandler? CloseButtonClicked;
|
||||
|
||||
public TradeChatMessageTemplate()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void NameCopyButton_Clicked(object _, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is not TraderMessage traderMessage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.NameCopyClicked?.Invoke(this, traderMessage);
|
||||
}
|
||||
|
||||
private void MessageCopyButton_Clicked(object _, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is not TraderMessage traderMessage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.MessageCopyClicked?.Invoke(this, traderMessage);
|
||||
}
|
||||
|
||||
private void TimestampCopyButton_Clicked(object _, EventArgs e)
|
||||
{
|
||||
if (this.DataContext is not TraderMessage traderMessage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.TimestampCopyClicked?.Invoke(this, traderMessage);
|
||||
}
|
||||
|
||||
private void CloseButton_Clicked(object _, EventArgs e)
|
||||
{
|
||||
this.CloseButtonClicked?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Height="30">
|
||||
Height="40">
|
||||
<WrapPanel
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top">
|
||||
@@ -45,7 +45,8 @@
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"/>
|
||||
<Border
|
||||
BorderBrush="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
BorderThickness="0, 0, 0, 1"
|
||||
Height="40"/>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<controls:SearchTextBox
|
||||
@@ -91,94 +92,18 @@
|
||||
Fill="{StaticResource Daybreak.Brushes.Background}"
|
||||
Grid.RowSpan="3"
|
||||
Visibility="{Binding ElementName=_this, Path=MessageOverlayVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></Rectangle>
|
||||
<Grid Grid.RowSpan="3"
|
||||
<local:TradeChatMessageTemplate
|
||||
Grid.RowSpan="3"
|
||||
MaxWidth="600"
|
||||
MaxHeight="400"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
DataContext="{Binding ElementName=_this, Path=SelectedTraderMessage, Mode=OneWay}"
|
||||
Background="{StaticResource MahApps.Brushes.ThemeBackground}"
|
||||
Visibility="{Binding ElementName=_this, Path=MessageOverlayVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Border
|
||||
BorderBrush="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
Grid.RowSpan="4"></Border>
|
||||
<WrapPanel
|
||||
Margin="10, 10, 10, 0"
|
||||
Grid.Row="0">
|
||||
<TextBlock
|
||||
Text="Player name: "
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox
|
||||
Text="{Binding ElementName=_this, Path=SelectedTraderMessage.Sender, Mode=OneWay}"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
FontSize="16"
|
||||
TextWrapping="Wrap"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="False"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
<buttons:CopyButton Height="20" Width="20"
|
||||
Clicked="NameCopyButton_Clicked"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel
|
||||
Margin="10, 0, 10, 0"
|
||||
Grid.Row="1">
|
||||
<TextBlock
|
||||
Text="Message: "
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox
|
||||
Text="{Binding ElementName=_this, Path=SelectedTraderMessage.Message, Mode=OneWay}"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
FontSize="16"
|
||||
TextWrapping="Wrap"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="False"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
<buttons:CopyButton Height="20" Width="20"
|
||||
Clicked="MessageCopyButton_Clicked"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel
|
||||
Margin="10, 0, 10, 0"
|
||||
Grid.Row="2">
|
||||
<TextBlock
|
||||
Text="Posted at: "
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox
|
||||
Text="{Binding ElementName=_this, Path=SelectedTraderMessage.Timestamp, Mode=OneWay, Converter={StaticResource DateTimeConverter}}"
|
||||
Foreground="{StaticResource MahApps.Brushes.Accent}"
|
||||
FontSize="16"
|
||||
TextWrapping="Wrap"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="False"
|
||||
BorderThickness="0, 0, 0, 1"/>
|
||||
<buttons:CopyButton Height="20" Width="20"
|
||||
Clicked="TimestampCopyButton_Clicked"/>
|
||||
</WrapPanel>
|
||||
<buttons:HighlightButton
|
||||
Grid.Row="3"
|
||||
Title="Close"
|
||||
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
Background="{StaticResource Daybreak.Brushes.Background}"
|
||||
FontSize="16"
|
||||
HighlightColor="{StaticResource MahApps.Brushes.Accent}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
BorderBrush="{StaticResource MahApps.Brushes.ThemeForeground}"
|
||||
BorderThickness="1"
|
||||
TextPadding="5"
|
||||
Margin="10"
|
||||
Clicked="CloseButton_Clicked"></buttons:HighlightButton>
|
||||
</Grid>
|
||||
Visibility="{Binding ElementName=_this, Path=MessageOverlayVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
NameCopyClicked="TradeChatMessageTemplate_NameCopyClicked"
|
||||
MessageCopyClicked="TradeChatMessageTemplate_MessageCopyClicked"
|
||||
TimestampCopyClicked="TradeChatMessageTemplate_TimestampCopyClicked"
|
||||
CloseButtonClicked="TradeChatMessageTemplate_CloseButtonClicked"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Daybreak.Models.Trade;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Trade;
|
||||
using Daybreak.Services.TradeChat;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Core.Extensions;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.Threading;
|
||||
@@ -11,6 +14,7 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
@@ -23,6 +27,7 @@ public partial class TradeChatTemplate : UserControl
|
||||
private readonly TimeSpan timeUpdateInterval = TimeSpan.FromSeconds(1);
|
||||
private readonly object collectionLock = new();
|
||||
private readonly DispatcherTimer dispatcherTimer = new();
|
||||
private readonly IWordHighlightingService wordHighlightingService;
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
private DateTime? lastQueryTime;
|
||||
private DateTime nextQueryTime = DateTime.Now;
|
||||
@@ -47,7 +52,13 @@ public partial class TradeChatTemplate : UserControl
|
||||
public ObservableCollection<TraderMessageViewWrapper> TraderMessages { get; } = new();
|
||||
|
||||
public TradeChatTemplate()
|
||||
: this(Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IWordHighlightingService>())
|
||||
{
|
||||
}
|
||||
|
||||
private TradeChatTemplate(IWordHighlightingService wordHighlightingService)
|
||||
{
|
||||
this.wordHighlightingService = wordHighlightingService.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
@@ -67,11 +78,6 @@ public partial class TradeChatTemplate : UserControl
|
||||
this.SelectedTraderMessage = traderMessage;
|
||||
}
|
||||
|
||||
private void CloseButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.MessageOverlayVisible = false;
|
||||
}
|
||||
|
||||
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
@@ -109,35 +115,6 @@ public partial class TradeChatTemplate : UserControl
|
||||
process.Start();
|
||||
}
|
||||
|
||||
private void NameCopyButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.SelectedTraderMessage is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.NameCopyClicked?.Invoke(this, this.SelectedTraderMessage);
|
||||
}
|
||||
|
||||
private void MessageCopyButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.SelectedTraderMessage is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.MessageCopyClicked?.Invoke(this, this.SelectedTraderMessage);
|
||||
}
|
||||
|
||||
private void TimestampCopyButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (this.SelectedTraderMessage is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.TimestampCopyClicked?.Invoke(this, this.SelectedTraderMessage);
|
||||
}
|
||||
|
||||
private void InitializeLatestTrades()
|
||||
{
|
||||
@@ -165,14 +142,39 @@ public partial class TradeChatTemplate : UserControl
|
||||
await this.GetLiveData(this.cancellationTokenSource?.Token ?? CancellationToken.None);
|
||||
}
|
||||
|
||||
private void TradeChatMessageTemplate_NameCopyClicked(object _, TraderMessage e)
|
||||
{
|
||||
this.NameCopyClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void TradeChatMessageTemplate_MessageCopyClicked(object _, TraderMessage e)
|
||||
{
|
||||
this.MessageCopyClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void TradeChatMessageTemplate_TimestampCopyClicked(object _, TraderMessage e)
|
||||
{
|
||||
this.TimestampCopyClicked?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void TradeChatMessageTemplate_CloseButtonClicked(object _, EventArgs __)
|
||||
{
|
||||
this.MessageOverlayVisible = false;
|
||||
}
|
||||
|
||||
private async Task GetLiveData(CancellationToken cancellationToken)
|
||||
{
|
||||
var foregroundColor = this.FindResource("MahApps.Brushes.ThemeForeground").Cast<SolidColorBrush>();
|
||||
var buyColor = this.FindResource("Daybreak.Brushes.Blue").Cast<SolidColorBrush>();
|
||||
var sellColor = this.FindResource("Daybreak.Brushes.DeepPurple").Cast<SolidColorBrush>();
|
||||
var tradeColor = this.FindResource("Daybreak.Brushes.DeepOrange").Cast<SolidColorBrush>();
|
||||
await foreach(var tradeMessage in this.TradeChatService.GetLiveTraderMessages(cancellationToken))
|
||||
{
|
||||
var wrapper = new TraderMessageViewWrapper
|
||||
{
|
||||
UpdateTimer = this.dispatcherTimer,
|
||||
TraderMessage = tradeMessage
|
||||
TraderMessage = tradeMessage,
|
||||
ColoredTextElements = this.wordHighlightingService.ParseString(tradeMessage.Message, foregroundColor, buyColor, sellColor, tradeColor)
|
||||
};
|
||||
|
||||
await this.Dispatcher.InvokeAsync(() => this.TraderMessages.Insert(0, wrapper));
|
||||
@@ -183,6 +185,10 @@ public partial class TradeChatTemplate : UserControl
|
||||
{
|
||||
await this.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var foregroundColor = this.FindResource("MahApps.Brushes.ThemeForeground").Cast<SolidColorBrush>();
|
||||
var buyColor = this.FindResource("Daybreak.Brushes.Blue").Cast<SolidColorBrush>();
|
||||
var sellColor = this.FindResource("Daybreak.Brushes.DeepPurple").Cast<SolidColorBrush>();
|
||||
var tradeColor = this.FindResource("Daybreak.Brushes.DeepOrange").Cast<SolidColorBrush>();
|
||||
this.TraderMessages.Clear();
|
||||
foreach (var traderMessage in traderMessages)
|
||||
{
|
||||
@@ -190,8 +196,9 @@ public partial class TradeChatTemplate : UserControl
|
||||
{
|
||||
UpdateTimer = this.dispatcherTimer,
|
||||
TraderMessage = traderMessage,
|
||||
Initialized = !animate
|
||||
});
|
||||
Initialized = !animate,
|
||||
ColoredTextElements = this.wordHighlightingService.ParseString(traderMessage.Message, foregroundColor, buyColor, sellColor, tradeColor)
|
||||
}); ;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,11 +36,21 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Text="{Binding TraderMessage.Message}"
|
||||
FontSize="16"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Left" />
|
||||
<ItemsControl ItemsSource="{Binding ColoredTextElements, Mode=OneWay}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Text, Mode=OneWay}"
|
||||
Foreground="{Binding Color, Mode=OneWay}"
|
||||
FontSize="16"
|
||||
Margin="2"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Bottom"
|
||||
|
||||
@@ -46,7 +46,6 @@ public partial class TradeMessageTemplate : UserControl
|
||||
}
|
||||
|
||||
this.UpdateDispatcherTimer(traderMessageViewWrapper.UpdateTimer);
|
||||
|
||||
if (traderMessageViewWrapper.Initialized)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -53,6 +53,6 @@ public partial class TradeQuoteTemplate : UserControl
|
||||
}
|
||||
|
||||
this.ImageVisible = true;
|
||||
this.ImageSource = this.imageCache.GetImage(imageUri);
|
||||
this.ImageSource = await this.imageCache.GetImage(imageUri).ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Daybreak.Converters;
|
||||
|
||||
public sealed class BooleanToGridLengthConverter : IValueConverter
|
||||
{
|
||||
private static GridLength Collapsed = new(0);
|
||||
|
||||
public GridLength VisibleValue { get; set; }
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return this.GetVisibility(value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private object GetVisibility(object value)
|
||||
{
|
||||
if (value is not bool)
|
||||
{
|
||||
return this.VisibleValue;
|
||||
}
|
||||
|
||||
var objValue = value.Cast<bool>();
|
||||
if (objValue)
|
||||
{
|
||||
return this.VisibleValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@ using System.Windows.Data;
|
||||
namespace Daybreak.Converters;
|
||||
public sealed class DateTimeConverter : IValueConverter
|
||||
{
|
||||
public string? Format { get; set; }
|
||||
public bool LongTime { get; set; }
|
||||
public bool LongDate { get; set; }
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not DateTime dateTime)
|
||||
@@ -12,6 +16,21 @@ public sealed class DateTimeConverter : IValueConverter
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (this.Format is not null)
|
||||
{
|
||||
return dateTime.ToString(this.Format);
|
||||
}
|
||||
|
||||
if (this.LongTime)
|
||||
{
|
||||
return dateTime.ToLongTimeString();
|
||||
}
|
||||
|
||||
if (this.LongDate)
|
||||
{
|
||||
return dateTime.ToLongDateString();
|
||||
}
|
||||
|
||||
return dateTime.ToShortDateString();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Daybreak.Converters;
|
||||
|
||||
public sealed class TimespanToETAConverter : IValueConverter
|
||||
{
|
||||
private const char PluralAppend = 's';
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return GetETAString(value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static string GetETAString(object obj)
|
||||
{
|
||||
if (obj is not TimeSpan timeSpan)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if ((int)timeSpan.TotalDays > 0)
|
||||
{
|
||||
return $"{(int)timeSpan.TotalDays} day{((int)timeSpan.TotalDays > 1 ? PluralAppend : string.Empty)} remaining";
|
||||
}
|
||||
|
||||
return $"{(int)timeSpan.Hours:D2}:{(int)timeSpan.Minutes:D2}:{(int)timeSpan.Seconds:D2} remaining";
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,16 @@
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
|
||||
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
|
||||
<Version>0.9.8.52</Version>
|
||||
<Version>0.9.8.102</Version>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<UserSecretsId>cfb2a489-db80-448d-a969-80270f314c46</UserSecretsId>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\NotifyClose.wav" />
|
||||
<None Remove="Resources\NotifyError.wav" />
|
||||
<None Remove="Resources\NotifyInformation.wav" />
|
||||
<None Remove="Services\Drawing\Resources\Bag.svg" />
|
||||
<None Remove="Services\Drawing\Resources\CircledStar.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Dungeon.svg" />
|
||||
@@ -27,6 +30,7 @@
|
||||
<None Remove="Services\Drawing\Resources\DungeonKey.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Flag.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Person.svg" />
|
||||
<None Remove="Services\Drawing\Resources\QuestionMark.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Scroll.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Skull.svg" />
|
||||
<None Remove="Services\Drawing\Resources\StairsDown.svg" />
|
||||
@@ -34,12 +38,16 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\NotifyClose.wav" />
|
||||
<EmbeddedResource Include="Resources\NotifyError.wav" />
|
||||
<EmbeddedResource Include="Resources\NotifyInformation.wav" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Bag.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\CircledStar.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Dungeon.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\DungeonBoss.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Flag.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Person.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\QuestionMark.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Scroll.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Skull.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\StairsDown.svg" />
|
||||
@@ -69,16 +77,18 @@
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.16" />
|
||||
<PackageReference Include="AvalonEdit" Version="6.3.0.90" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.52" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-beta.710" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.4.10" />
|
||||
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1774.30" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1938.49" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageReference Include="NAudio" Version="2.2.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageReference Include="Slim" Version="1.9.2" />
|
||||
@@ -88,11 +98,11 @@
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.6.2" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard.DependencyInjection" Version="1.3.1" />
|
||||
<PackageReference Include="WpfExtended" Version="0.7.2" />
|
||||
<PackageReference Include="WpfExtended.SourceGeneration" Version="0.1.1" />
|
||||
<PackageReference Include="WpfExtended.SourceGeneration" Version="0.1.2" />
|
||||
<PackageReference Include="WpfScreenHelper" Version="2.1.0" />
|
||||
<PackageReference Include="WriteableBitmapEx" Version="1.6.8" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
||||
<Exec Command="echo.>$(Version).version" />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user