feat(desktop): add licence processing
This commit is contained in:
parent
033d4add13
commit
0416c9efaa
|
@ -31,7 +31,7 @@ namespace XIVChat_Desktop {
|
|||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
private void Application_Startup(object sender, StartupEventArgs e) {
|
||||
private async void Application_Startup(object sender, StartupEventArgs e) {
|
||||
try {
|
||||
this.Config = Configuration.Load() ?? new Configuration();
|
||||
} catch (Exception ex) {
|
||||
|
@ -62,12 +62,24 @@ namespace XIVChat_Desktop {
|
|||
)
|
||||
);
|
||||
|
||||
var wnd = new MainWindow();
|
||||
this.Window = wnd;
|
||||
|
||||
// I guess this gets initialised where you call it the first time, so initialise it on the UI thread
|
||||
this.Dispatcher.Invoke(() => { });
|
||||
|
||||
#if RELEASE
|
||||
if (string.IsNullOrWhiteSpace(this.Config.LicenceKey) || !(await LicenceWindow.LicenceInfo(this.Config.LicenceKey)).Valid()) {
|
||||
var lic = new LicenceWindow(null, true);
|
||||
lic.Show();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
this.InitialiseWindow();
|
||||
}
|
||||
|
||||
public void InitialiseWindow() {
|
||||
var wnd = new MainWindow();
|
||||
this.Window = wnd;
|
||||
|
||||
wnd.Show();
|
||||
|
||||
// initialise a config window to apply all our settings
|
||||
|
|
|
@ -16,6 +16,8 @@ namespace XIVChat_Desktop {
|
|||
public class Configuration : INotifyPropertyChanged {
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
public string? LicenceKey { get; set; }
|
||||
|
||||
public KeyPair KeyPair { get; set; } = PublicKeyBox.GenerateKeyPair();
|
||||
|
||||
public ObservableCollection<SavedServer> Servers { get; set; } = new ObservableCollection<SavedServer>();
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<Window x:Class="XIVChat_Desktop.LicenceWindow"
|
||||
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:XIVChat_Desktop"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
ui:WindowHelper.UseModernWindowStyle="True"
|
||||
mc:Ignorable="d"
|
||||
Title="Licence"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
ContentRendered="LicenceWindow_OnContentRendered"
|
||||
SizeToContent="WidthAndHeight"
|
||||
d:DataContext="{d:DesignInstance local:LicenceWindow}">
|
||||
<StackPanel Margin="8">
|
||||
<ProgressBar x:Name="Loading"
|
||||
IsIndeterminate="True" />
|
||||
<StackPanel x:Name="LicenceInfoPanel"
|
||||
Visibility="Collapsed">
|
||||
<TextBlock x:Name="LicenceDescription"
|
||||
Text="Checking licence..." />
|
||||
<TextBox x:Name="LicenceKey"
|
||||
Text="{Binding App.Config.LicenceKey}"
|
||||
ui:ControlHelper.Header="Licence key" />
|
||||
<Button x:Name="CheckButton"
|
||||
Margin="0,8,0,0"
|
||||
Content="Check"
|
||||
Click="Check_Click"
|
||||
IsEnabled="False" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
|
@ -0,0 +1,123 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Windows.Web.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace XIVChat_Desktop {
|
||||
public partial class LicenceWindow {
|
||||
public App App => (App)Application.Current;
|
||||
|
||||
private readonly bool startAfterSuccess;
|
||||
|
||||
public LicenceWindow(Window? owner, bool startAfterSuccess) {
|
||||
this.Owner = owner;
|
||||
this.startAfterSuccess = startAfterSuccess;
|
||||
this.InitializeComponent();
|
||||
this.DataContext = this;
|
||||
|
||||
var empty = string.IsNullOrWhiteSpace(this.App.Config.LicenceKey);
|
||||
if (empty) {
|
||||
this.CheckButton.IsEnabled = true;
|
||||
this.LicenceDescription.Text = "No licence key has been supplied. Please enter one.";
|
||||
this.SetLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_ = Task.Run(async () => {
|
||||
await this.Check();
|
||||
this.Dispatch(() => this.SetLoading(false));
|
||||
});
|
||||
}
|
||||
|
||||
private void SetLoading(bool loading) {
|
||||
this.Loading.Visibility = loading ? Visibility.Visible : Visibility.Collapsed;
|
||||
this.LicenceInfoPanel.Visibility = loading ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
|
||||
private async Task<bool> Check(bool increment = false) {
|
||||
this.Dispatch(() => this.CheckButton.IsEnabled = false);
|
||||
|
||||
var licence = await LicenceInfo(this.App.Config.LicenceKey!, increment);
|
||||
var valid = licence.Valid();
|
||||
|
||||
this.Dispatch(() => {
|
||||
this.CheckButton.IsEnabled = true;
|
||||
this.LicenceDescription.Text = valid
|
||||
? $"Valid licence key for {licence.purchase.email}. Thank you!"
|
||||
: "Invalid licence key. Please check the key and try again.";
|
||||
});
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
private async void Check_Click(object sender, RoutedEventArgs e) {
|
||||
this.App.Config.Save();
|
||||
|
||||
var valid = await this.Check(true);
|
||||
|
||||
if (!valid || !this.startAfterSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.App.InitialiseWindow();
|
||||
this.Close();
|
||||
}
|
||||
|
||||
public static async Task<LicenceResponse> LicenceInfo(string key, bool increment = false) {
|
||||
var uri = new Uri("https://api.gumroad.com/v2/licenses/verify");
|
||||
var data = new Dictionary<string, string> {
|
||||
["product_permalink"] = "kvQIw",
|
||||
["license_key"] = key,
|
||||
["increment_uses_count"] = increment ? "true" : "false",
|
||||
};
|
||||
|
||||
var client = new HttpClient();
|
||||
var res = await client.PostAsync(uri, new HttpFormUrlEncodedContent(data));
|
||||
var response = JsonConvert.DeserializeObject<LicenceResponse>(await res.Content.ReadAsStringAsync());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private void LicenceWindow_OnContentRendered(object? sender, EventArgs e) {
|
||||
this.InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
public class LicenceResponse {
|
||||
public readonly bool success;
|
||||
public readonly uint uses;
|
||||
public readonly Purchase purchase;
|
||||
|
||||
public LicenceResponse(bool success, uint uses, Purchase purchase) {
|
||||
this.success = success;
|
||||
this.uses = uses;
|
||||
this.purchase = purchase;
|
||||
}
|
||||
|
||||
public bool Valid() {
|
||||
return this.success && !this.purchase.refunded && !this.purchase.chargebacked;
|
||||
}
|
||||
}
|
||||
|
||||
public class Purchase {
|
||||
public readonly string id;
|
||||
public readonly string productName;
|
||||
public readonly DateTime createdAt;
|
||||
public readonly string fullName;
|
||||
public readonly bool refunded;
|
||||
public readonly bool chargebacked;
|
||||
public readonly string email;
|
||||
|
||||
public Purchase(string id, string productName, DateTime createdAt, string fullName, bool refunded, bool chargebacked, string email) {
|
||||
this.id = id;
|
||||
this.productName = productName;
|
||||
this.createdAt = createdAt;
|
||||
this.fullName = fullName;
|
||||
this.refunded = refunded;
|
||||
this.chargebacked = chargebacked;
|
||||
this.email = email;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,8 @@
|
|||
<MenuItem Header="Export"
|
||||
Click="Export_Click" />
|
||||
<Separator />
|
||||
<MenuItem Header="Licence"
|
||||
Click="Licence_Click" />
|
||||
<MenuItem Header="Configuration"
|
||||
Click="Configuration_Click" />
|
||||
</MenuItem>
|
||||
|
|
|
@ -185,5 +185,9 @@ namespace XIVChat_Desktop {
|
|||
private void Export_Click(object sender, RoutedEventArgs e) {
|
||||
new Export(this).Show();
|
||||
}
|
||||
|
||||
private void Licence_Click(object sender, RoutedEventArgs e) {
|
||||
new LicenceWindow(this, false).Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue