Compare commits

..
13 Commits
21 changed files with 424 additions and 100 deletions
@@ -6,11 +6,19 @@ namespace Daybreak.Configuration
{
[JsonProperty("GamePath")]
public string GamePath { get; set; }
[JsonProperty("ToolboxPath")]
public string ToolboxPath { get; set; }
[JsonProperty("CharacterName")]
public string CharacterName { get; set; }
[JsonProperty("LeftBrowserDefault")]
public string LeftBrowserDefault { get; set; }
[JsonProperty("RightBrowserDefault")]
public string RightBrowserDefault { get; set; }
[JsonProperty("ProtectedUsername")]
public string ProtectedUsername { get; set; }
[JsonProperty("ProtectedPassword")]
public string ProtectedPassword { get; set; }
[JsonProperty("AddressBarReadonly")]
public bool AddressBarReadonly { get; set; } = true;
}
}
@@ -1,13 +1,13 @@
using Daybreak.Services.ApplicationDetection;
using Daybreak.Services.ApplicationLifetime;
using Daybreak.Services.Bloogum;
using Daybreak.Services.Configuration;
using Daybreak.Services.Credentials;
using Daybreak.Services.Logging;
using Daybreak.Services.Screenshots;
using Daybreak.Services.ViewManagement;
using Daybreak.Views;
using Microsoft.Web.WebView2.Core;
using Palletizer.WPF.Services.ConfigurationManager;
using Slim;
using System.Extensions;
@@ -42,7 +42,7 @@ namespace Daybreak.Configuration
{
viewProducer.ThrowIfNull(nameof(viewProducer));
viewProducer.RegisterView<StartupView>();
viewProducer.RegisterView<MainView>();
viewProducer.RegisterView<SettingsView>();
}
}
@@ -48,12 +48,18 @@
</WrapPanel>
<TextBox Text="{Binding ElementName=_this, Path=Address, Mode=OneWay}" FontSize="16"
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Grid.Column="1" IsReadOnly="True" Background="Transparent"
Grid.Column="1" IsReadOnly="{Binding ElementName=_this, Path=AddressBarReadonly, Mode=OneWay}" Background="Transparent"
BorderThickness="1" VerticalAlignment="Center" VerticalContentAlignment="Center"
BorderBrush="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></TextBox>
<local:StarGlyph Grid.Column="2" Height="30" Width="30" Margin="5"
BorderBrush="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
PreviewKeyDown="TextBox_PreviewKeyDown"></TextBox>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<local:StarGlyph Height="30" Width="30" Margin="5"
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Clicked="StarGlyph_Clicked" x:Name="FavoriteButton"></local:StarGlyph>
<local:MaximizeButton Height="30" Width="30" Margin="5"
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Clicked="MaximizeButton_Clicked"></local:MaximizeButton>
</StackPanel>
</Grid>
</Grid>
</UserControl>
@@ -1,4 +1,5 @@
using Daybreak.Launch;
using Daybreak.Services.Configuration;
using Microsoft.Web.WebView2.Core;
using System;
using System.Extensions;
@@ -16,32 +17,39 @@ namespace Daybreak.Controls
public readonly static DependencyProperty AddressProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, string>(nameof(Address));
public readonly static DependencyProperty FavoriteAddressProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, string>(nameof(FavoriteAddress));
public readonly static DependencyProperty NavigatingProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(Navigating));
public readonly static DependencyProperty AddressBarReadonlyProperty = DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, bool>(nameof(AddressBarReadonly));
public event EventHandler<string> FavoriteUriChanged;
public event EventHandler MaximizeClicked;
private readonly CoreWebView2Environment coreWebView2Environment;
private readonly IConfigurationManager configurationManager;
public string Address
{
get => this.GetTypedValue<string>(AddressProperty);
set => this.SetTypedValue(AddressProperty, value);
}
public string FavoriteAddress
{
get => this.GetTypedValue<string>(FavoriteAddressProperty);
set => this.SetTypedValue(FavoriteAddressProperty, value);
}
public bool Navigating
{
get => this.GetTypedValue<bool>(NavigatingProperty);
private set => this.SetTypedValue<bool>(NavigatingProperty, value);
}
public bool AddressBarReadonly
{
get => this.GetTypedValue<bool>(AddressBarReadonlyProperty);
private set => this.SetTypedValue<bool>(AddressBarReadonlyProperty, value);
}
public ChromiumBrowserWrapper()
{
this.coreWebView2Environment = Launcher.ApplicationServiceManager.GetService<CoreWebView2Environment>();
this.configurationManager = Launcher.ApplicationServiceManager.GetService<IConfigurationManager>();
this.InitializeComponent();
this.InitializeBrowser();
}
@@ -55,14 +63,37 @@ namespace Daybreak.Controls
}
}
public void ReinitializeBrowser()
{
this.InitializeBrowser();
}
private async void InitializeBrowser()
{
await this.WebBrowser.EnsureCoreWebView2Async(this.coreWebView2Environment);
this.AddressBarReadonly = this.configurationManager.GetConfiguration().AddressBarReadonly;
this.WebBrowser.CoreWebView2.NewWindowRequested += (browser, args) => args.Handled = true;
this.WebBrowser.NavigationStarting += (browser, args) => this.Navigating = true;
this.WebBrowser.NavigationCompleted += (browser, args) => this.Navigating = false;
}
private void TextBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Enter)
{
var newAddress = sender.As<TextBox>().Text;
newAddress = SanitizeAddress(newAddress);
if (newAddress is null)
{
return;
}
this.Address = newAddress;
this.WebBrowser.CoreWebView2.Navigate(this.Address);
e.Handled = true;
}
}
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
{
this.WebBrowser.Dispose();
@@ -71,16 +102,19 @@ namespace Daybreak.Controls
private void BackButton_Clicked(object sender, EventArgs e)
{
this.WebBrowser.GoBack();
this.Address = this.WebBrowser.Source.ToString();
}
private void ForwardButton_Clicked(object sender, EventArgs e)
{
this.WebBrowser.GoForward();
this.Address = this.WebBrowser.Source.ToString();
}
private void RefreshGlyph_Clicked(object sender, EventArgs e)
{
this.WebBrowser.Reload();
this.Address = this.WebBrowser.Source.ToString();
}
private void CancelGlyph_Clicked(object sender, EventArgs e)
@@ -94,6 +128,11 @@ namespace Daybreak.Controls
this.FavoriteUriChanged?.Invoke(this, this.FavoriteAddress);
}
private void MaximizeButton_Clicked(object sender, EventArgs e)
{
this.MaximizeClicked?.Invoke(this, e);
}
private void CheckFavoriteAddress()
{
if (this.Address == this.FavoriteAddress)
@@ -105,5 +144,26 @@ namespace Daybreak.Controls
this.FavoriteButton.IsEnabled = true;
}
}
private static string SanitizeAddress(string address)
{
if (string.IsNullOrWhiteSpace(address))
{
return null;
}
if (address.StartsWith("www") is false &&
address.StartsWith("http") is false)
{
address = "https://www." + address;
}
else if (address.StartsWith("www"))
{
address = "https://" + address;
}
Uri.TryCreate(address, UriKind.Absolute, out var uri);
return uri?.ToString();
}
}
}
+39
View File
@@ -0,0 +1,39 @@
<UserControl x:Class="Daybreak.Controls.MaximizeButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Controls"
x:Name="_this"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="50">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.3*" />
<RowDefinition Height="1*" />
<RowDefinition Height="0.3*" />
</Grid.RowDefinitions>
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Opacity="0.6" Visibility="Hidden" Grid.RowSpan="3" Grid.ColumnSpan="3"></Ellipse>
<Viewbox Grid.Row="1" Grid.Column="1">
<Grid>
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Data="m30,0l-24,0a5.9966,5.9966 0 0 0 -6,6l0,24a6,6 0 0 0 12,0l0,-18l18,0a6,6 0 0 0 0,-12z"></Path>
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Data="m90,0l-24,0a6,6 0 0 0 0,12l18,0l0,18a6,6 0 0 0 12,0l0,-24a5.9966,5.9966 0 0 0 -6,-6z"></Path>
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Data="m30,84l-18,0l0,-18a6,6 0 0 0 -12,0l0,24a5.9966,5.9966 0 0 0 6,6l24,0a6,6 0 0 0 0,-12z"></Path>
<Path Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Data="m90,60a5.9966,5.9966 0 0 0 -6,6l0,18l-18,0a6,6 0 0 0 0,12l24,0a5.9966,5.9966 0 0 0 6,-6l0,-24a5.9966,5.9966 0 0 0 -6,-6z"></Path>
</Grid>
</Viewbox>
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" StrokeThickness="1" Fill="Transparent"
MouseEnter="Ellipse_MouseEnter" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
Grid.RowSpan="3" Grid.ColumnSpan="3"></Ellipse>
</Grid>
</UserControl>
+37
View File
@@ -0,0 +1,37 @@
using System;
using System.Windows.Controls;
using System.Windows.Input;
namespace Daybreak.Controls
{
/// <summary>
/// Interaction logic for SaveButton.xaml
/// </summary>
public partial class MaximizeButton : UserControl
{
public event EventHandler Clicked;
public MaximizeButton()
{
InitializeComponent();
}
private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
{
BackgroundEllipse.Visibility = System.Windows.Visibility.Visible;
}
private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
{
BackgroundEllipse.Visibility = System.Windows.Visibility.Hidden;
}
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
Clicked?.Invoke(this, e);
}
}
}
}
+6 -3
View File
@@ -9,16 +9,15 @@
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
<LangVersion>preview</LangVersion>
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
<Version>0.1</Version>
<Version>0.1.3</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Meziantou.Framework.Win32.CredentialManager" Version="1.4.0" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.774.44" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Slim" Version="1.2.1" />
<PackageReference Include="SystemExtensions.NetStandard" Version="1.1.3" />
<PackageReference Include="WCL" Version="1.0.1" />
<PackageReference Include="WCL" Version="1.0.2" />
<PackageReference Include="WpfExtended" Version="0.1.1" />
</ItemGroup>
@@ -38,6 +37,10 @@
</ItemGroup>
<ItemGroup>
<Page Update="Controls\MaximizeButton.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Controls\StarGlyph.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType>
+1 -1
View File
@@ -72,7 +72,7 @@
<Grid x:Name="Container" Grid.Row="1">
</Grid>
<wcl:TitleBar x:Name="Titlebar"
Background="Transparent" Text="" MouseLeftButtonDown="TitleBar_MouseLeftButtonDown"
Background="Transparent" MouseLeftButtonDown="TitleBar_MouseLeftButtonDown"
WindowState="Normal" MinimizeButtonClicked="TitleBar_MinimizeButtonClicked"
MaximizeButtonClicked="TitleBar_MaximizeButtonClicked"
RestoreButtonClicked="TitleBar_RestoreButtonClicked"
+1 -2
View File
@@ -47,7 +47,7 @@ namespace Daybreak.Launch
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.viewManager.ShowView<StartupView>();
this.viewManager.ShowView<MainView>();
this.SetupImageCycle();
}
@@ -134,7 +134,6 @@ namespace Daybreak.Launch
{
var avgColor = GetAverageColor(bitmapImage);
var luminace = GetLuminace(avgColor);
Debug.WriteLine(luminace);
if (luminace < 0.15)
{
this.Foreground = Brushes.White;
@@ -1,5 +1,5 @@
using Daybreak.Services.Credentials;
using Palletizer.WPF.Services.ConfigurationManager;
using Daybreak.Services.Configuration;
using Daybreak.Services.Credentials;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -11,12 +11,14 @@ namespace Daybreak.Services.ApplicationDetection
{
public class ApplicationDetector : IApplicationDetector
{
private const string ToolboxProcessName = "GWToolbox";
private const string ProcessName = "gw";
private readonly IConfigurationManager configurationManager;
private readonly ICredentialManager credentialManager;
public bool IsGuildwarsRunning => GuildwarsProcessDetected();
public bool IsToolboxRunning => GuildwarsToolboxProcessDetected();
public ApplicationDetector(
IConfigurationManager configurationManager,
@@ -41,21 +43,43 @@ namespace Daybreak.Services.ApplicationDetection
}
var auth = this.credentialManager.GetCredentials();
if (auth is null)
auth.Do(
onSome: (credentials) =>
{
if (Process.Start(executable, new List<string> { "-email", credentials.Username, "-password", credentials.Password, "-character", configuration.CharacterName }) is null)
{
throw new InvalidOperationException($"Unable to launch {executable}");
}
},
onNone: () =>
{
throw new InvalidOperationException($"No credentials available");
});
}
public void LaunchGuildwarsToolbox()
{
var configuration = this.configurationManager.GetConfiguration();
var executable = configuration.ToolboxPath;
if (File.Exists(executable) is false)
{
throw new InvalidOperationException($"No credentials available");
throw new InvalidOperationException($"Guildwars executable doesn't exist at {executable}");
}
if (Process.Start(executable, new List<string> { "-email", auth.Username, "-password", auth.Password, "-character", configuration.CharacterName }) is null)
if (Process.Start(executable) is null)
{
throw new InvalidOperationException($"Unable to launch executable");
throw new InvalidOperationException($"Unable to launch {executable}");
}
}
private static bool GuildwarsProcessDetected()
{
var process = Process.GetProcessesByName(ProcessName).FirstOrDefault();
return process is not null;
return Process.GetProcessesByName(ProcessName).FirstOrDefault() is not null;
}
private static bool GuildwarsToolboxProcessDetected()
{
return Process.GetProcessesByName(ToolboxProcessName).FirstOrDefault() is not null;
}
}
}
@@ -3,6 +3,8 @@
public interface IApplicationDetector
{
bool IsGuildwarsRunning { get; }
bool IsToolboxRunning { get; }
void LaunchGuildwars();
void LaunchGuildwarsToolbox();
}
}
@@ -4,7 +4,7 @@ using Daybreak.Utils;
using System;
using System.IO;
namespace Palletizer.WPF.Services.ConfigurationManager
namespace Daybreak.Services.Configuration
{
public sealed class ConfigurationManager : IConfigurationManager
{
@@ -1,6 +1,6 @@
using Daybreak.Configuration;
namespace Palletizer.WPF.Services.ConfigurationManager
namespace Daybreak.Services.Configuration
{
public interface IConfigurationManager
{
@@ -1,20 +1,65 @@
using Daybreak.Models;
using Daybreak.Services.Configuration;
using Daybreak.Services.Logging;
using Daybreak.Utils;
using System;
using System.Extensions;
using System.Security.Cryptography;
using System.Text;
namespace Daybreak.Services.Credentials
{
public sealed class CredentialManager : ICredentialManager
{
private const string Target = "GuildwarsLogin";
private static readonly byte[] Entropy = Convert.FromBase64String("R3VpbGR3YXJz");
private readonly ILogger logger;
private readonly IConfigurationManager configurationManager;
public LoginCredentials GetCredentials()
public CredentialManager(
ILogger logger,
IConfigurationManager configurationManager)
{
var credential = Meziantou.Framework.Win32.CredentialManager.ReadCredential(Target);
return new LoginCredentials { Username = credential.UserName, Password = credential.Password };
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
this.logger = logger.ThrowIfNull(nameof(logger));
}
public Optional<LoginCredentials> GetCredentials()
{
this.logger.LogInformation("Retrieving credentials");
var config = this.configurationManager.GetConfiguration();
if (string.IsNullOrEmpty(config.ProtectedUsername) ||
string.IsNullOrEmpty(config.ProtectedPassword))
{
this.logger.LogInformation("No credentials found");
return Optional.None<LoginCredentials>();
}
try
{
var usrbytes = Convert.FromBase64String(config.ProtectedUsername);
var psdBytes = Convert.FromBase64String(config.ProtectedPassword);
return new LoginCredentials
{
Username = Encoding.UTF8.GetString(ProtectedData.Unprotect(usrbytes, Entropy, DataProtectionScope.LocalMachine)),
Password = Encoding.UTF8.GetString(ProtectedData.Unprotect(psdBytes, Entropy, DataProtectionScope.LocalMachine))
};
}
catch(Exception e)
{
this.logger.LogError($"Unable to retrieve credentials. Details: {e}");
return Optional.None<LoginCredentials>();
}
}
public void StoreCredentials(LoginCredentials loginCredentials)
{
Meziantou.Framework.Win32.CredentialManager.WriteCredential(Target, loginCredentials.Username, loginCredentials.Password, Meziantou.Framework.Win32.CredentialPersistence.LocalMachine);
this.logger.LogInformation("Storing credentials");
var usrBytes = Encoding.UTF8.GetBytes(loginCredentials.Username);
var psdBytes = Encoding.UTF8.GetBytes(loginCredentials.Password);
var config = this.configurationManager.GetConfiguration();
config.ProtectedUsername = Convert.ToBase64String(ProtectedData.Protect(usrBytes, Entropy, DataProtectionScope.LocalMachine));
config.ProtectedPassword = Convert.ToBase64String(ProtectedData.Protect(psdBytes, Entropy, DataProtectionScope.LocalMachine));
this.configurationManager.SaveConfiguration(config);
}
}
}
@@ -1,10 +1,11 @@
using Daybreak.Models;
using System.Extensions;
namespace Daybreak.Services.Credentials
{
public interface ICredentialManager
{
void StoreCredentials(LoginCredentials loginCredentials);
LoginCredentials GetCredentials();
Optional<LoginCredentials> GetCredentials();
}
}
+48
View File
@@ -0,0 +1,48 @@
<UserControl x:Class="Daybreak.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Views"
xmlns:controls="clr-namespace:Daybreak.Controls"
xmlns:effects="clr-namespace:System.Windows.Media.Extensions.Effects;assembly=WpfExtended"
mc:Ignorable="d"
x:Name="_this"
Loaded="StartupView_Loaded"
Unloaded="StartupView_Unloaded"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibility"></BooleanToVisibilityConverter>
</UserControl.Resources>
<Grid Background="Transparent" x:Name="ViewContainer">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<controls:OpaqueButton Text="Launch game" Highlight="White" TransparentBackground="Black" HighlightOpacity="0.3" BackgroundOpacity="0.2"
Foreground="White" FontSize="36" Width="250" Height="60" VerticalAlignment="Bottom"
IsEnabled="{Binding ElementName=_this, Path=LaunchButtonEnabled, Mode=OneWay}"
Clicked="LaunchButton_Clicked" Grid.Row="0" Grid.ColumnSpan="3"></controls:OpaqueButton>
<controls:OpaqueButton Text="Launch toolbox" Highlight="White" TransparentBackground="Black" HighlightOpacity="0.3" BackgroundOpacity="0.2"
Foreground="White" FontSize="24" Width="200" Height="40" Margin="0, 10, 0, 10"
IsEnabled="{Binding ElementName=_this, Path=LaunchToolboxButtonEnabled, Mode=OneWay}"
Clicked="LaunchToolboxButton_Clicked" Grid.Row="1" Grid.ColumnSpan="3"></controls:OpaqueButton>
<Grid x:Name="RightContainer" Grid.Column="2" Margin="10">
<controls:ChromiumBrowserWrapper Address="{Binding ElementName=_this, Path=RightBrowserAddress, Mode=OneWay}"
Foreground="White" FavoriteUriChanged="RightBrowser_FavoriteUriChanged"
FavoriteAddress="{Binding ElementName=_this, Path=RightBrowserFavoriteAddress, Mode=OneWay}"
MaximizeClicked="RightChromiumBrowserWrapper_MaximizeClicked"/>
</Grid>
<Grid x:Name="LeftContainer" Grid.Column="0" Margin="10">
<controls:ChromiumBrowserWrapper Address="{Binding ElementName=_this, Path=LeftBrowserAddress, Mode=OneWay}"
Foreground="White" FavoriteUriChanged="LeftBrowser_FavoriteUriChanged"
FavoriteAddress="{Binding ElementName=_this, Path=LeftBrowserFavoriteAddress, Mode=OneWay}"
MaximizeClicked="LeftChromiumBrowserWrapper_MaximizeClicked"/>
</Grid>
</Grid>
</UserControl>
@@ -1,10 +1,10 @@
using Daybreak.Services.ApplicationDetection;
using Daybreak.Controls;
using Daybreak.Services.ApplicationDetection;
using Daybreak.Services.Configuration;
using Daybreak.Services.ViewManagement;
using Palletizer.WPF.Services.ConfigurationManager;
using System;
using System.Extensions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
@@ -14,24 +14,29 @@ namespace Daybreak.Views
/// <summary>
/// Interaction logic for StartupView.xaml
/// </summary>
public partial class StartupView : UserControl
public partial class MainView : UserControl
{
public static readonly DependencyProperty LaunchButtonEnabledProperty =
DependencyPropertyExtensions.Register<StartupView, bool>(nameof(LaunchButtonEnabled));
DependencyPropertyExtensions.Register<MainView, bool>(nameof(LaunchButtonEnabled));
public static readonly DependencyProperty LaunchToolboxButtonEnabledProperty =
DependencyPropertyExtensions.Register<MainView, bool>(nameof(LaunchToolboxButtonEnabled));
public static readonly DependencyProperty RightBrowserAddressProperty =
DependencyPropertyExtensions.Register<StartupView, string>(nameof(RightBrowserAddress));
DependencyPropertyExtensions.Register<MainView, string>(nameof(RightBrowserAddress));
public static readonly DependencyProperty LeftBrowserAddressProperty =
DependencyPropertyExtensions.Register<StartupView, string>(nameof(LeftBrowserAddress));
DependencyPropertyExtensions.Register<MainView, string>(nameof(LeftBrowserAddress));
public static readonly DependencyProperty RightBrowserFavoriteAddressProperty =
DependencyPropertyExtensions.Register<StartupView, string>(nameof(RightBrowserFavoriteAddress));
DependencyPropertyExtensions.Register<MainView, string>(nameof(RightBrowserFavoriteAddress));
public static readonly DependencyProperty LeftBrowserFavoriteAddressProperty =
DependencyPropertyExtensions.Register<StartupView, string>(nameof(LeftBrowserFavoriteAddress));
DependencyPropertyExtensions.Register<MainView, string>(nameof(LeftBrowserFavoriteAddress));
private readonly IApplicationDetector applicationDetector;
private readonly IViewManager viewManager;
private readonly IConfigurationManager configurationManager;
private readonly CancellationTokenSource cancellationTokenSource = new();
private bool leftBrowserMaximized = false;
private bool rightBrowserMaximized = false;
public string RightBrowserFavoriteAddress
{
get => this.GetTypedValue<string>(RightBrowserFavoriteAddressProperty);
@@ -57,8 +62,13 @@ namespace Daybreak.Views
get => this.GetTypedValue<bool>(LaunchButtonEnabledProperty);
set => this.SetTypedValue(LaunchButtonEnabledProperty, value);
}
public bool LaunchToolboxButtonEnabled
{
get => this.GetTypedValue<bool>(LaunchToolboxButtonEnabledProperty);
set => this.SetTypedValue(LaunchToolboxButtonEnabledProperty, value);
}
public StartupView(
public MainView(
IApplicationDetector applicationDetector,
IViewManager viewManager,
IConfigurationManager configurationManager)
@@ -87,14 +97,8 @@ namespace Daybreak.Views
private void CheckGameState()
{
if (applicationDetector.IsGuildwarsRunning)
{
this.LaunchButtonEnabled = false;
}
else
{
this.LaunchButtonEnabled = true;
}
this.LaunchButtonEnabled = applicationDetector.IsGuildwarsRunning is false;
this.LaunchToolboxButtonEnabled = applicationDetector.IsToolboxRunning is false;
}
private void StartupView_Loaded(object sender, RoutedEventArgs e)
@@ -106,7 +110,7 @@ namespace Daybreak.Views
this.cancellationTokenSource.Cancel();
}
private void OpaqueButton_Clicked(object sender, EventArgs e)
private void LaunchButton_Clicked(object sender, EventArgs e)
{
try
{
@@ -118,6 +122,18 @@ namespace Daybreak.Views
}
}
private void LaunchToolboxButton_Clicked(object sender, EventArgs e)
{
try
{
this.applicationDetector.LaunchGuildwarsToolbox();
}
catch
{
this.viewManager.ShowView<SettingsView>();
}
}
private void LeftBrowser_FavoriteUriChanged(object sender, string e)
{
var config = this.configurationManager.GetConfiguration();
@@ -131,5 +147,41 @@ namespace Daybreak.Views
config.RightBrowserDefault = e;
this.configurationManager.SaveConfiguration(config);
}
private void LeftChromiumBrowserWrapper_MaximizeClicked(object sender, EventArgs e)
{
if (this.leftBrowserMaximized)
{
this.ViewContainer.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[1].Width = new GridLength(1, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[2].Width = new GridLength(1, GridUnitType.Star);
}
else
{
this.ViewContainer.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[1].Width = new GridLength(0, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[2].Width = new GridLength(0, GridUnitType.Star);
}
this.leftBrowserMaximized = !this.leftBrowserMaximized;
}
private void RightChromiumBrowserWrapper_MaximizeClicked(object sender, EventArgs e)
{
if (this.rightBrowserMaximized)
{
this.ViewContainer.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[1].Width = new GridLength(1, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[2].Width = new GridLength(1, GridUnitType.Star);
}
else
{
this.ViewContainer.ColumnDefinitions[0].Width = new GridLength(0, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[1].Width = new GridLength(0, GridUnitType.Star);
this.ViewContainer.ColumnDefinitions[2].Width = new GridLength(1, GridUnitType.Star);
}
this.rightBrowserMaximized = !this.rightBrowserMaximized;
}
}
}
+12 -1
View File
@@ -15,6 +15,8 @@
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
@@ -38,6 +40,15 @@
x:Name="GamePathTextbox" FontSize="22" Margin="0, 0, 30, 0" Background="Transparent" Foreground="White"></TextBox>
<controls:FilePickerGlyph Grid.Row="4" Grid.Column="1" Height="30" Width="30" HorizontalAlignment="Right"
Foreground="White" BorderBrush="Gray" BorderThickness="1"
Clicked="FilePickerGlyph_Clicked"></controls:FilePickerGlyph>
Clicked="GameFilePickerGlyph_Clicked"></controls:FilePickerGlyph>
<TextBlock Text="Toolbox path: " FontSize="22" Foreground="White" Grid.Row="5"></TextBlock>
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.Row="5"
x:Name="ToolboxPathTextbox" FontSize="22" Margin="0, 0, 30, 0" Background="Transparent" Foreground="White"></TextBox>
<controls:FilePickerGlyph Grid.Row="5" Grid.Column="1" Height="30" Width="30" HorizontalAlignment="Right"
Foreground="White" BorderBrush="Gray" BorderThickness="1"
Clicked="ToolboxFilePickerGlyph_Clicked"></controls:FilePickerGlyph>
<TextBlock Text="Address bar readonly: " FontSize="22" Foreground="White" Grid.Row="6"/>
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.Row="6"
x:Name="AddressBarReadonlyTextbox" FontSize="22" Background="Transparent" Foreground="White"></TextBox>
</Grid>
</UserControl>
+35 -10
View File
@@ -1,13 +1,10 @@
using Daybreak.Configuration;
using Daybreak.Models;
using Daybreak.Models;
using Daybreak.Services.Configuration;
using Daybreak.Services.Credentials;
using Daybreak.Services.ViewManagement;
using Microsoft.Win32;
using Palletizer.WPF.Services.ConfigurationManager;
using System.Extensions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
namespace Daybreak.Views
{
@@ -36,10 +33,17 @@ namespace Daybreak.Views
{
var config = this.configurationManager.GetConfiguration();
var creds = this.credentialManager.GetCredentials();
this.UsernameTextbox.Text = creds.Username;
this.PasswordBox.Password = creds.Password;
creds.DoAny(
onSome: (credentials) =>
{
this.UsernameTextbox.Text = credentials.Username;
this.PasswordBox.Password = credentials.Password;
});
this.AddressBarReadonlyTextbox.Text = config.AddressBarReadonly.ToString();
this.CharacterTextbox.Text = config.CharacterName;
this.GamePathTextbox.Text = config.GamePath;
this.ToolboxPathTextbox.Text = config.ToolboxPath;
}
private void SaveButton_Clicked(object sender, System.EventArgs e)
@@ -47,12 +51,18 @@ namespace Daybreak.Views
var currentConfig = this.configurationManager.GetConfiguration();
currentConfig.CharacterName = this.CharacterTextbox.Text;
currentConfig.GamePath = this.GamePathTextbox.Text;
currentConfig.ToolboxPath = this.ToolboxPathTextbox.Text;
if (bool.TryParse(this.AddressBarReadonlyTextbox.Text, out var addressBarReadonly))
{
currentConfig.AddressBarReadonly = addressBarReadonly;
}
this.configurationManager.SaveConfiguration(currentConfig);
this.credentialManager.StoreCredentials(new LoginCredentials { Username = this.UsernameTextbox.Text, Password = this.PasswordBox.Password });
this.viewManager.ShowView<StartupView>();
this.viewManager.ShowView<MainView>();
}
private void FilePickerGlyph_Clicked(object sender, System.EventArgs e)
private void GameFilePickerGlyph_Clicked(object sender, System.EventArgs e)
{
var filePicker = new OpenFileDialog()
{
@@ -67,9 +77,24 @@ namespace Daybreak.Views
}
}
private void ToolboxFilePickerGlyph_Clicked(object sender, System.EventArgs e)
{
var filePicker = new OpenFileDialog()
{
CheckFileExists = true,
CheckPathExists = true,
DefaultExt = "exe",
Multiselect = false
};
if (filePicker.ShowDialog() is true)
{
this.ToolboxPathTextbox.Text = filePicker.FileName;
}
}
private void BackButton_Clicked(object sender, System.EventArgs e)
{
this.viewManager.ShowView<StartupView>();
this.viewManager.ShowView<MainView>();
}
}
}
-40
View File
@@ -1,40 +0,0 @@
<UserControl x:Class="Daybreak.Views.StartupView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Views"
xmlns:controls="clr-namespace:Daybreak.Controls"
xmlns:effects="clr-namespace:System.Windows.Media.Extensions.Effects;assembly=WpfExtended"
mc:Ignorable="d"
x:Name="_this"
Loaded="StartupView_Loaded"
Unloaded="StartupView_Unloaded"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibility"></BooleanToVisibilityConverter>
</UserControl.Resources>
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<controls:OpaqueButton Text="Launch game" Highlight="White" TransparentBackground="Black" HighlightOpacity="0.3" BackgroundOpacity="0.2"
Foreground="White" FontSize="36" Width="250" Height="60" VerticalAlignment="Bottom" Margin="0, 0, 0, 30"
IsEnabled="{Binding ElementName=_this, Path=LaunchButtonEnabled, Mode=OneWay}"
Clicked="OpaqueButton_Clicked" Grid.Row="1" Grid.ColumnSpan="3"></controls:OpaqueButton>
<controls:ChromiumBrowserWrapper Grid.Column="2" Margin="10" Address="{Binding ElementName=_this, Path=RightBrowserAddress, Mode=OneWay}"
Foreground="White" FavoriteUriChanged="RightBrowser_FavoriteUriChanged"
FavoriteAddress="{Binding ElementName=_this, Path=RightBrowserFavoriteAddress, Mode=OneWay}"/>
<controls:ChromiumBrowserWrapper Grid.Column="0" Margin="10" Address="{Binding ElementName=_this, Path=LeftBrowserAddress, Mode=OneWay}"
Foreground="White" FavoriteUriChanged="LeftBrowser_FavoriteUriChanged"
FavoriteAddress="{Binding ElementName=_this, Path=LeftBrowserFavoriteAddress, Mode=OneWay}"/>
</Grid>
</UserControl>
+5 -1
View File
@@ -1,10 +1,14 @@
# Daybreak
Custom client for Guildwars.
Requires standalone version https://developer.microsoft.com/microsoft-edge/webview2.
![Alt Text](https://media1.giphy.com/media/Z32o0OZ5pZHDOIodzD/giphy.gif)
![Alt Text](https://media0.giphy.com/media/aQ8Wl7lsuhT0AblCPI/giphy.gif)
## Features
Automatically detect if guildwars is running or not. Includes the ability to launch guildwars from the client.
Manages username and password combination. Stores them in Windows Credential Manager.
Manages username and password combination.
Ability to set a character name which gets autoloaded during launch.