feat: add better relay support to desktop
This commit is contained in:
parent
6d95b0d850
commit
617f9717a2
|
@ -30,16 +30,7 @@ namespace XIVChat_Desktop {
|
|||
|
||||
public string? LastHost { get; set; }
|
||||
|
||||
private Connection? connection;
|
||||
|
||||
public Connection? Connection {
|
||||
get => this.connection;
|
||||
set {
|
||||
this.connection = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Connection)));
|
||||
this.ConnectionStatusChanged();
|
||||
}
|
||||
}
|
||||
public Connection? Connection { get; set; }
|
||||
|
||||
public bool Connected => this.Connection != null;
|
||||
|
||||
|
@ -125,16 +116,12 @@ namespace XIVChat_Desktop {
|
|||
};
|
||||
}
|
||||
|
||||
private void ConnectionStatusChanged() {
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Connected)));
|
||||
}
|
||||
|
||||
public void Connect(string host, ushort port, string? relayAuth, string? relayTarget) {
|
||||
public void Connect(string host, ushort port) {
|
||||
if (this.Connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.Connection = new Connection(this, host, port, relayAuth, relayTarget);
|
||||
this.Connection = new Connection(this, host, port);
|
||||
this.Connection.ReceiveMessage += this.OnReceiveMessage;
|
||||
Task.Run(this.Connection.Connect);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ using System.ComponentModel;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using XIVChatCommon.Message;
|
||||
using XIVChatCommon.Message.Server;
|
||||
|
@ -30,56 +29,20 @@ namespace XIVChat_Desktop {
|
|||
|
||||
public bool AlwaysOnTop { get; set; }
|
||||
|
||||
private double fontSize = 14d;
|
||||
|
||||
public double FontSize {
|
||||
get => this.fontSize;
|
||||
set {
|
||||
this.fontSize = value;
|
||||
this.OnPropertyChanged(nameof(this.FontSize));
|
||||
}
|
||||
}
|
||||
public double FontSize { get; set; } = 14d;
|
||||
|
||||
public ushort BacklogMessages { get; set; } = 500;
|
||||
|
||||
public uint LocalBacklogMessages { get; set; } = 10_000;
|
||||
|
||||
private double opacity = 1.0;
|
||||
public double Opacity { get; set; } = 1.0;
|
||||
|
||||
public double Opacity {
|
||||
get => this.opacity;
|
||||
set {
|
||||
this.opacity = value;
|
||||
this.OnPropertyChanged(nameof(this.Opacity));
|
||||
}
|
||||
}
|
||||
public bool CompactMode { get; set; }
|
||||
|
||||
private bool compactMode;
|
||||
|
||||
public bool CompactMode {
|
||||
get => this.compactMode;
|
||||
set {
|
||||
this.compactMode = value;
|
||||
this.OnPropertyChanged(nameof(this.CompactMode));
|
||||
}
|
||||
}
|
||||
|
||||
private Theme theme = Theme.System;
|
||||
|
||||
public Theme Theme {
|
||||
get => this.theme;
|
||||
set {
|
||||
this.theme = value;
|
||||
this.OnPropertyChanged(nameof(this.Theme));
|
||||
}
|
||||
}
|
||||
public Theme Theme { get; set; } = Theme.System;
|
||||
|
||||
public ObservableCollection<Notification> Notifications { get; set; } = new ObservableCollection<Notification>();
|
||||
|
||||
private void OnPropertyChanged(string propName) {
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
|
||||
}
|
||||
|
||||
#region io
|
||||
|
||||
private static string FilePath() => Path.Join(
|
||||
|
@ -98,6 +61,7 @@ namespace XIVChat_Desktop {
|
|||
using var json = new JsonTextReader(reader);
|
||||
|
||||
var serializer = new JsonSerializer {
|
||||
TypeNameHandling = TypeNameHandling.Auto,
|
||||
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||
};
|
||||
return serializer.Deserialize<Configuration>(json);
|
||||
|
@ -113,81 +77,39 @@ namespace XIVChat_Desktop {
|
|||
using var file = File.CreateText(path);
|
||||
using var json = new JsonTextWriter(file);
|
||||
|
||||
var serialiser = new JsonSerializer();
|
||||
var serialiser = new JsonSerializer {
|
||||
TypeNameHandling = TypeNameHandling.Auto,
|
||||
};
|
||||
serialiser.Serialize(json, this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SavedServer : INotifyPropertyChanged {
|
||||
private string _name;
|
||||
private string _host;
|
||||
private ushort _port;
|
||||
private string? _relayAuth;
|
||||
private string? _relayTarget;
|
||||
|
||||
public string Name {
|
||||
get => this._name;
|
||||
set {
|
||||
this._name = value;
|
||||
this.OnPropertyChanged(nameof(this.Name));
|
||||
}
|
||||
}
|
||||
|
||||
public string Host {
|
||||
get => this._host;
|
||||
set {
|
||||
this._host = value;
|
||||
this.OnPropertyChanged(nameof(this.Host));
|
||||
}
|
||||
}
|
||||
|
||||
public ushort Port {
|
||||
get => this._port;
|
||||
set {
|
||||
this._port = value;
|
||||
this.OnPropertyChanged(nameof(this.Port));
|
||||
}
|
||||
}
|
||||
|
||||
public string? RelayAuth {
|
||||
get => this._relayAuth;
|
||||
set {
|
||||
this._relayAuth = value;
|
||||
this.OnPropertyChanged(nameof(this.RelayAuth));
|
||||
}
|
||||
}
|
||||
|
||||
public string? RelayTarget {
|
||||
get => this._relayTarget;
|
||||
set {
|
||||
this._relayTarget = value;
|
||||
this.OnPropertyChanged(nameof(this.RelayTarget));
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SavedServer : INotifyPropertyChanged {
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) {
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class DirectServer : SavedServer {
|
||||
public string Host { get; set; }
|
||||
|
||||
public ushort Port { get; set; }
|
||||
|
||||
public DirectServer(string name, string host, ushort port) {
|
||||
this.Name = name;
|
||||
this.Host = host;
|
||||
this.Port = port;
|
||||
}
|
||||
|
||||
public SavedServer(string name, string host, ushort port, string? relayAuth, string? relayTarget) {
|
||||
this._name = name;
|
||||
this._host = host;
|
||||
this._port = port;
|
||||
this._relayAuth = relayAuth;
|
||||
this._relayTarget = relayTarget;
|
||||
}
|
||||
|
||||
protected bool Equals(SavedServer other) {
|
||||
protected bool Equals(DirectServer other) {
|
||||
return this.Name == other.Name && this.Host == other.Host && this.Port == other.Port;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) {
|
||||
if (obj is null) {
|
||||
if (ReferenceEquals(null, obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -195,12 +117,47 @@ namespace XIVChat_Desktop {
|
|||
return true;
|
||||
}
|
||||
|
||||
return obj.GetType() == this.GetType() && this.Equals((SavedServer)obj);
|
||||
return obj.GetType() == this.GetType() && this.Equals((DirectServer) obj);
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
|
||||
public override int GetHashCode() {
|
||||
return HashCode.Combine(this.Name, this.Host, this.Port);
|
||||
unchecked {
|
||||
return (this.Host.GetHashCode() * 397) ^ this.Port.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class RelayServer : SavedServer {
|
||||
public string RelayAuth { get; set; }
|
||||
public string RelayTarget { get; set; }
|
||||
|
||||
public RelayServer(string name, string relayAuth, string relayTarget) {
|
||||
this.Name = name;
|
||||
this.RelayAuth = relayAuth;
|
||||
this.RelayTarget = relayTarget;
|
||||
}
|
||||
|
||||
protected bool Equals(RelayServer other) {
|
||||
return this.Name == other.Name && this.RelayAuth == other.RelayAuth && this.RelayTarget == other.RelayTarget;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) {
|
||||
if (ReferenceEquals(null, obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(this, obj)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return obj.GetType() == this.GetType() && this.Equals((RelayServer) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
unchecked {
|
||||
return (this.RelayAuth.GetHashCode() * 397) ^ this.RelayTarget.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,34 +180,19 @@ namespace XIVChat_Desktop {
|
|||
|
||||
[JsonObject]
|
||||
public class Tab : IEnumerable<ServerMessage>, INotifyCollectionChanged, INotifyPropertyChanged {
|
||||
private string name;
|
||||
private bool processMarkdown;
|
||||
|
||||
public Tab(string name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get => this.name;
|
||||
set {
|
||||
this.name = value;
|
||||
this.OnPropertyChanged(nameof(this.Name));
|
||||
}
|
||||
}
|
||||
public string Name { get; set; }
|
||||
|
||||
public Filter Filter { get; set; } = new Filter();
|
||||
|
||||
public bool ProcessMarkdown {
|
||||
get => this.processMarkdown;
|
||||
set {
|
||||
this.processMarkdown = value;
|
||||
this.OnPropertyChanged(nameof(this.ProcessMarkdown));
|
||||
}
|
||||
}
|
||||
public bool ProcessMarkdown { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<ServerMessage> Messages { get; } = new List<ServerMessage>();
|
||||
|
||||
public Tab(string name) {
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
private void NotifyReset() {
|
||||
this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
@ -278,21 +220,21 @@ namespace XIVChat_Desktop {
|
|||
this.NotifyReset();
|
||||
}
|
||||
|
||||
private int lastSequence = -1;
|
||||
private int insertAt;
|
||||
private int _lastSequence = -1;
|
||||
private int _insertAt;
|
||||
|
||||
public void AddReversedChunk(ServerMessage[] messages, int sequence, Configuration config) {
|
||||
if (sequence != this.lastSequence) {
|
||||
this.lastSequence = sequence;
|
||||
this.insertAt = this.Messages.Count;
|
||||
if (sequence != this._lastSequence) {
|
||||
this._lastSequence = sequence;
|
||||
this._insertAt = this.Messages.Count;
|
||||
}
|
||||
|
||||
var filtered = messages
|
||||
.Where(msg => msg.Channel == 0 || this.Filter.Allowed(msg))
|
||||
.ToList();
|
||||
|
||||
this.Messages.InsertRange(this.insertAt, filtered);
|
||||
this.NotifyAddItemsAt(filtered, this.insertAt);
|
||||
this.Messages.InsertRange(this._insertAt, filtered);
|
||||
this.NotifyAddItemsAt(filtered, this._insertAt);
|
||||
|
||||
this.Prune(config);
|
||||
}
|
||||
|
@ -314,8 +256,8 @@ namespace XIVChat_Desktop {
|
|||
return;
|
||||
}
|
||||
|
||||
var removed = this.Messages.Take((int)diff).ToList();
|
||||
this.Messages.RemoveRange(0, (int)diff);
|
||||
var removed = this.Messages.Take((int) diff).ToList();
|
||||
this.Messages.RemoveRange(0, (int) diff);
|
||||
this.NotifyRemoveItemsAt(removed, 0);
|
||||
}
|
||||
|
||||
|
@ -365,10 +307,6 @@ namespace XIVChat_Desktop {
|
|||
|
||||
public event NotifyCollectionChangedEventHandler? CollectionChanged;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) {
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
|
@ -376,7 +314,7 @@ namespace XIVChat_Desktop {
|
|||
public HashSet<FilterType> Types { get; set; } = new HashSet<FilterType>();
|
||||
|
||||
public virtual bool Allowed(ServerMessage message) {
|
||||
var code = new ChatCode((ushort)message.Channel);
|
||||
var code = new ChatCode((ushort) message.Channel);
|
||||
return this.Types.Any(type => type.Allowed(code));
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +326,7 @@ namespace XIVChat_Desktop {
|
|||
public List<ChatType> Channels { get; set; } = new List<ChatType>();
|
||||
public List<string> Substrings { get; set; } = new List<string>();
|
||||
|
||||
private IReadOnlyCollection<String> regexes = new List<string>();
|
||||
private IReadOnlyCollection<string> regexes = new List<string>();
|
||||
|
||||
public IReadOnlyCollection<string> Regexes {
|
||||
get => this.regexes;
|
||||
|
|
|
@ -31,7 +31,9 @@ namespace XIVChat_Desktop {
|
|||
return;
|
||||
}
|
||||
|
||||
this.App.Connect(server.Host, server.Port, server.RelayAuth, server.RelayTarget);
|
||||
if (server is DirectServer direct) {
|
||||
this.App.Connect(direct.Host, direct.Port);
|
||||
}
|
||||
|
||||
this.Close();
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ using System.Threading.Channels;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using MessagePack;
|
||||
using XIVChatCommon;
|
||||
using XIVChatCommon.Message;
|
||||
using XIVChatCommon.Message.Client;
|
||||
using XIVChatCommon.Message.Relay;
|
||||
using XIVChatCommon.Message.Server;
|
||||
|
||||
namespace XIVChat_Desktop {
|
||||
|
@ -58,23 +60,18 @@ namespace XIVChat_Desktop {
|
|||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
public string? CurrentChannel { get; private set; }
|
||||
|
||||
private bool available;
|
||||
public bool Available { get; set; }
|
||||
|
||||
public bool Available {
|
||||
get => this.available;
|
||||
private set {
|
||||
this.available = value;
|
||||
this.OnPropertyChanged(nameof(this.Available));
|
||||
}
|
||||
}
|
||||
|
||||
public Connection(App app, string host, ushort port, string? relayAuth = null, string? relayTarget = null) {
|
||||
public Connection(App app, string host, ushort port) {
|
||||
this.app = app;
|
||||
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.relayAuth = relayAuth;
|
||||
this.relayTarget = relayTarget;
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private void OnAvailableChanged() {
|
||||
this.app.Window.OnPropertyChanged(nameof(MainWindow.InputPlaceholder));
|
||||
}
|
||||
|
||||
public void SendMessage(string message) {
|
||||
|
@ -112,39 +109,47 @@ namespace XIVChat_Desktop {
|
|||
|
||||
var stream = this.client.GetStream();
|
||||
|
||||
switch (usingRelay) {
|
||||
// do relay auth before connecting if necessary
|
||||
case true: {
|
||||
var relayHandshake = await KeyExchange.ClientHandshake(this.app.Config.KeyPair, stream);
|
||||
// write the magic bytes
|
||||
await stream.WriteAsync(new byte[] {
|
||||
14, 20, 67,
|
||||
});
|
||||
|
||||
// ensure the relay's public key is what we expect
|
||||
if (!relayHandshake.RemotePublicKey.SequenceEqual(RelayPublicKey)) {
|
||||
this.app.Dispatch(() => {
|
||||
MessageBox.Show("Unexpected relay public key.");
|
||||
});
|
||||
return;
|
||||
}
|
||||
// authenticate with relay if necessary
|
||||
if (usingRelay) {
|
||||
var relayHandshake = await KeyExchange.ClientHandshake(this.app.Config.KeyPair, stream);
|
||||
|
||||
// send auth token
|
||||
var authBytes = Encoding.UTF8.GetBytes(this.relayAuth!);
|
||||
await SecretMessage.SendSecretMessage(stream, relayHandshake.Keys.tx, authBytes);
|
||||
|
||||
// TODO: receive response
|
||||
|
||||
// send the public key of the server
|
||||
var pk = Util.StringToByteArray(this.relayTarget!);
|
||||
await SecretMessage.SendSecretMessage(stream, relayHandshake.Keys.tx, pk);
|
||||
|
||||
// TODO: receive response
|
||||
break;
|
||||
}
|
||||
// only send magic bytes if not using the relay
|
||||
case false:
|
||||
// write the magic bytes
|
||||
await stream.WriteAsync(new byte[] {
|
||||
14, 20, 67,
|
||||
// ensure the relay's public key is what we expect
|
||||
if (!relayHandshake.RemotePublicKey.SequenceEqual(RelayPublicKey)) {
|
||||
this.app.Dispatch(() => {
|
||||
MessageBox.Show("Unexpected relay public key.");
|
||||
});
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
async Task<RelaySuccess> ReadSuccess() {
|
||||
var response = await SecretMessage.ReadSecretMessage(stream, relayHandshake.Keys.rx);
|
||||
return MessagePackSerializer.Deserialize<RelaySuccess>(response);
|
||||
}
|
||||
|
||||
// send auth token
|
||||
var authBytes = Encoding.UTF8.GetBytes(this.relayAuth!);
|
||||
await SecretMessage.SendSecretMessage(stream, relayHandshake.Keys.tx, authBytes);
|
||||
|
||||
var authSuccess = await ReadSuccess();
|
||||
if (!authSuccess.Success) {
|
||||
this.app.Dispatch(() => MessageBox.Show($"Relay rejected authentication code:\n{authSuccess.Info}"));
|
||||
return;
|
||||
}
|
||||
|
||||
// send the public key of the server
|
||||
var pk = Util.StringToByteArray(this.relayTarget!);
|
||||
await SecretMessage.SendSecretMessage(stream, relayHandshake.Keys.tx, pk);
|
||||
|
||||
var targetSuccess = await ReadSuccess();
|
||||
if (!targetSuccess.Success) {
|
||||
this.app.Dispatch(() => MessageBox.Show($"Relay rejected server public key:\n{targetSuccess.Info}"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// do the handshake
|
||||
|
@ -360,11 +365,7 @@ namespace XIVChat_Desktop {
|
|||
case ServerOperation.Channel:
|
||||
var channel = ServerChannel.Decode(payload);
|
||||
|
||||
this.CurrentChannel = channel.name;
|
||||
|
||||
this.app.Dispatch(() => {
|
||||
this.OnPropertyChanged(nameof(this.CurrentChannel));
|
||||
});
|
||||
this.app.Dispatch(() => this.CurrentChannel = channel.name);
|
||||
break;
|
||||
case ServerOperation.Backlog:
|
||||
var backlog = ServerBacklog.Decode(payload);
|
||||
|
@ -421,22 +422,5 @@ namespace XIVChat_Desktop {
|
|||
window.Location.Visibility = visibility;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnPropertyChanged(string prop) {
|
||||
Action action;
|
||||
|
||||
if (prop == nameof(this.Available)) {
|
||||
action = () => {
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Available)));
|
||||
this.app.Window.OnPropertyChanged(nameof(MainWindow.InputPlaceholder));
|
||||
};
|
||||
} else {
|
||||
action = () => {
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
|
||||
};
|
||||
}
|
||||
|
||||
this.app.Dispatch(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ namespace XIVChat_Desktop.Controls {
|
|||
private Window Window => Window.GetWindow(this)!;
|
||||
|
||||
public IEnumerable<SavedServer> ItemsSource {
|
||||
get { return (IEnumerable<SavedServer>)this.GetValue(ItemsSourceProperty); }
|
||||
set { this.SetValue(ItemsSourceProperty, value); }
|
||||
get => (IEnumerable<SavedServer>)this.GetValue(ItemsSourceProperty);
|
||||
set => this.SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
|
||||
public Visibility ControlsVisibility {
|
||||
get { return (Visibility)this.GetValue(ControlsVisibilityProperty); }
|
||||
set { this.SetValue(ControlsVisibilityProperty, value); }
|
||||
get => (Visibility)this.GetValue(ControlsVisibilityProperty);
|
||||
set => this.SetValue(ControlsVisibilityProperty, value);
|
||||
}
|
||||
|
||||
public SavedServer? SelectedServer {
|
||||
|
|
4
XIVChat Desktop/FodyWeavers.xml
Normal file
4
XIVChat Desktop/FodyWeavers.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<PropertyChanged />
|
||||
</Weavers>
|
|
@ -10,6 +10,7 @@
|
|||
WindowStartupLocation="CenterOwner"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Title="Manage server"
|
||||
Initialized="ManageServer_OnInitialized"
|
||||
d:DataContext="{d:DesignInstance local:ManageServer}">
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
|
@ -18,8 +19,6 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
|
@ -32,8 +31,10 @@
|
|||
Grid.Column="0">
|
||||
Server type
|
||||
</Label>
|
||||
<ComboBox Grid.Row="0"
|
||||
<ComboBox x:Name="TypeBox"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
SelectionChanged="TypeBox_OnSelectionChanged"
|
||||
SelectedIndex="0">
|
||||
<ComboBoxItem>Direct</ComboBoxItem>
|
||||
<ComboBoxItem>Relay</ComboBoxItem>
|
||||
|
@ -50,7 +51,8 @@
|
|||
x:Name="ServerName"
|
||||
Text="{Binding Server.Name, Mode=OneTime}" />
|
||||
|
||||
<Label VerticalAlignment="Center"
|
||||
<Label x:Name="ServerHostLabel"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Row="2"
|
||||
Grid.Column="0">
|
||||
IP Address
|
||||
|
@ -61,7 +63,8 @@
|
|||
x:Name="ServerHost"
|
||||
Text="{Binding Server.Host, Mode=OneTime}" />
|
||||
|
||||
<Label VerticalAlignment="Center"
|
||||
<Label x:Name="ServerPortLabel"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Row="3"
|
||||
Grid.Column="0">
|
||||
Port
|
||||
|
@ -73,32 +76,34 @@
|
|||
Text="{Binding Server.Port, Mode=OneTime}"
|
||||
ui:ControlHelper.PlaceholderText="14777" />
|
||||
|
||||
<Label VerticalAlignment="Center"
|
||||
Grid.Row="4"
|
||||
<Label x:Name="RelayAuthLabel"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Row="2"
|
||||
Grid.Column="0">
|
||||
Relay auth
|
||||
</Label>
|
||||
<TextBox Margin="4,4,0,0"
|
||||
Grid.Row="4"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
x:Name="RelayAuth"
|
||||
Text="{Binding Server.RelayAuth, Mode=OneTime}"
|
||||
ui:ControlHelper.PlaceholderText="Optional (only enter if using relay)" />
|
||||
ui:ControlHelper.PlaceholderText="Your authentication code" />
|
||||
|
||||
<Label VerticalAlignment="Center"
|
||||
Grid.Row="5"
|
||||
<Label x:Name="RelayTargetLabel"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Row="3"
|
||||
Grid.Column="0">
|
||||
Server public key
|
||||
</Label>
|
||||
<TextBox Margin="4,4,0,0"
|
||||
Grid.Row="5"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
x:Name="RelayTarget"
|
||||
Text="{Binding Server.RelayTarget, Mode=OneTime}"
|
||||
ui:ControlHelper.PlaceholderText="Optional (only enter if using relay)" />
|
||||
ui:ControlHelper.PlaceholderText="AABBCCDD..." />
|
||||
|
||||
<WrapPanel Margin="0,8,0,0"
|
||||
Grid.Row="6"
|
||||
Grid.Row="4"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Right">
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System.Windows;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace XIVChat_Desktop {
|
||||
/// <summary>
|
||||
|
@ -8,17 +10,19 @@ namespace XIVChat_Desktop {
|
|||
public App App => (App) Application.Current;
|
||||
public SavedServer? Server { get; private set; }
|
||||
|
||||
private readonly bool isNewServer;
|
||||
private bool IsDirect => this.TypeBox.SelectedIndex == 0;
|
||||
|
||||
private readonly bool _isNewServer;
|
||||
|
||||
public ManageServer(Window owner, SavedServer? server) {
|
||||
this.Owner = owner;
|
||||
this.Server = server;
|
||||
this.isNewServer = server == null;
|
||||
this._isNewServer = server == null;
|
||||
|
||||
this.InitializeComponent();
|
||||
this.DataContext = this;
|
||||
|
||||
if (this.isNewServer) {
|
||||
if (this._isNewServer) {
|
||||
this.Title = "Add server";
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +30,7 @@ namespace XIVChat_Desktop {
|
|||
public ManageServer(Window owner, SavedServer server, bool isNewServer) {
|
||||
this.Owner = owner;
|
||||
this.Server = server;
|
||||
this.isNewServer = isNewServer;
|
||||
this._isNewServer = isNewServer;
|
||||
|
||||
this.InitializeComponent();
|
||||
this.DataContext = this;
|
||||
|
@ -34,49 +38,55 @@ namespace XIVChat_Desktop {
|
|||
|
||||
private void Save_Click(object sender, RoutedEventArgs e) {
|
||||
var serverName = this.ServerName.Text;
|
||||
var serverHost = this.ServerHost.Text;
|
||||
var relayAuth = this.RelayAuth.Text.Trim();
|
||||
var relayTarget = this.RelayTarget.Text.Trim();
|
||||
|
||||
if (relayAuth.Length == 0) {
|
||||
relayAuth = null;
|
||||
}
|
||||
|
||||
if (relayTarget.Length == 0) {
|
||||
relayTarget = null;
|
||||
}
|
||||
|
||||
if (serverName.Length == 0 || serverHost.Length == 0) {
|
||||
MessageBox.Show("Server must have a name and host.");
|
||||
if (serverName.Length == 0) {
|
||||
MessageBox.Show("Server must have a name.");
|
||||
return;
|
||||
}
|
||||
|
||||
ushort port;
|
||||
if (this.ServerPort.Text.Length == 0) {
|
||||
port = 14777;
|
||||
} else {
|
||||
if (!ushort.TryParse(this.ServerPort.Text, out port) || port < 1) {
|
||||
MessageBox.Show("Port was not valid. It must be a number between 1 and 65535.");
|
||||
if (this.IsDirect) {
|
||||
var serverHost = this.ServerHost.Text.Trim();
|
||||
|
||||
if (serverHost.Length == 0) {
|
||||
MessageBox.Show("Server must have a host.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isNewServer) {
|
||||
this.Server = new SavedServer(
|
||||
serverName,
|
||||
serverHost,
|
||||
port,
|
||||
relayAuth,
|
||||
relayTarget
|
||||
);
|
||||
ushort port;
|
||||
if (this.ServerPort.Text.Length == 0) {
|
||||
port = 14777;
|
||||
} else {
|
||||
if (!ushort.TryParse(this.ServerPort.Text, out port) || port < 1) {
|
||||
MessageBox.Show("Port was not valid. It must be a number between 1 and 65535.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.App.Config.Servers.Add(this.Server);
|
||||
if (this._isNewServer) {
|
||||
this.Server = new DirectServer(serverName, serverHost, port);
|
||||
this.App.Config.Servers.Add(this.Server);
|
||||
} else if (this.Server is DirectServer direct) {
|
||||
this.Server!.Name = serverName;
|
||||
direct.Host = serverHost;
|
||||
direct.Port = port;
|
||||
}
|
||||
} else {
|
||||
this.Server!.Name = serverName;
|
||||
this.Server.Host = serverHost;
|
||||
this.Server.Port = port;
|
||||
this.Server.RelayAuth = relayAuth;
|
||||
this.Server.RelayTarget = relayTarget;
|
||||
var relayAuth = this.RelayAuth.Text.Trim();
|
||||
var relayTarget = this.RelayTarget.Text.Trim();
|
||||
|
||||
if (relayAuth.Length == 0 || relayTarget.Length == 0) {
|
||||
MessageBox.Show("Server must have an auth code and public key.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._isNewServer) {
|
||||
this.Server = new RelayServer(serverName, relayAuth, relayTarget);
|
||||
this.App.Config.Servers.Add(this.Server);
|
||||
} else if (this.Server is RelayServer relay) {
|
||||
this.Server!.Name = serverName;
|
||||
relay.RelayAuth = relayAuth;
|
||||
relay.RelayTarget = relayTarget;
|
||||
}
|
||||
}
|
||||
|
||||
this.App.Config.Save();
|
||||
|
@ -87,5 +97,49 @@ namespace XIVChat_Desktop {
|
|||
private void Cancel_Click(object sender, RoutedEventArgs e) {
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void TypeBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
this.CalcVisibility();
|
||||
}
|
||||
|
||||
private void CalcVisibility() {
|
||||
try {
|
||||
if (this.IsDirect) {
|
||||
this.ServerHostLabel.Visibility = Visibility.Visible;
|
||||
this.ServerHost.Visibility = Visibility.Visible;
|
||||
this.ServerPortLabel.Visibility = Visibility.Visible;
|
||||
this.ServerPort.Visibility = Visibility.Visible;
|
||||
this.RelayAuthLabel.Visibility = Visibility.Collapsed;
|
||||
this.RelayAuth.Visibility = Visibility.Collapsed;
|
||||
this.RelayTargetLabel.Visibility = Visibility.Collapsed;
|
||||
this.RelayTarget.Visibility = Visibility.Collapsed;
|
||||
} else {
|
||||
this.ServerHostLabel.Visibility = Visibility.Collapsed;
|
||||
this.ServerHost.Visibility = Visibility.Collapsed;
|
||||
this.ServerPortLabel.Visibility = Visibility.Collapsed;
|
||||
this.ServerPort.Visibility = Visibility.Collapsed;
|
||||
this.RelayAuthLabel.Visibility = Visibility.Visible;
|
||||
this.RelayAuth.Visibility = Visibility.Visible;
|
||||
this.RelayTargetLabel.Visibility = Visibility.Visible;
|
||||
this.RelayTarget.Visibility = Visibility.Visible;
|
||||
}
|
||||
} catch (NullReferenceException) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void ManageServer_OnInitialized(object? sender, EventArgs e) {
|
||||
this.TypeBox.SelectedIndex = this.Server switch {
|
||||
RelayServer _ => 1,
|
||||
DirectServer _ => 0,
|
||||
_ => this.TypeBox.SelectedIndex,
|
||||
};
|
||||
|
||||
if (this.Server != null) {
|
||||
this.TypeBox.IsEnabled = false;
|
||||
}
|
||||
|
||||
this.CalcVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace XIVChat_Desktop {
|
|||
continue;
|
||||
}
|
||||
|
||||
var saved = new SavedServer(server.playerName, server.address, server.port, null, null);
|
||||
var saved = new DirectServer(server.playerName, server.address, server.port);
|
||||
if (this.Servers.Contains(saved)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -51,11 +51,18 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Fody" Version="6.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.0.8" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="6.1.1" />
|
||||
<PackageReference Include="ModernWpfUI" Version="0.9.2" />
|
||||
<PackageReference Include="ModernWpfUI.MahApps" Version="0.9.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="3.3.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Sodium.Core" Version="1.2.3" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue
Block a user