2020-10-23 21:24:32 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2020-11-08 01:10:29 +00:00
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
2020-10-23 21:24:32 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
using System.Windows.Media;
|
2020-11-01 01:31:10 +00:00
|
|
|
|
using XIVChatCommon;
|
2020-10-23 21:24:32 +00:00
|
|
|
|
|
|
|
|
|
namespace XIVChat_Desktop {
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Interaction logic for MainWindow.xaml
|
|
|
|
|
/// </summary>
|
2020-11-08 01:10:29 +00:00
|
|
|
|
public partial class MainWindow : INotifyPropertyChanged {
|
2020-11-01 01:31:10 +00:00
|
|
|
|
public App App => (App)Application.Current;
|
|
|
|
|
|
2020-11-06 00:48:21 +00:00
|
|
|
|
public List<ServerMessage> Messages { get; } = new List<ServerMessage>();
|
2020-11-01 01:31:10 +00:00
|
|
|
|
|
2020-11-08 01:10:29 +00:00
|
|
|
|
public string InputPlaceholder => this.App.Connection?.Available == true ? "Send a message..." : "Chat is currently unavailable";
|
|
|
|
|
|
2020-10-23 21:24:32 +00:00
|
|
|
|
public MainWindow() {
|
2020-11-01 01:31:10 +00:00
|
|
|
|
this.InitializeComponent();
|
|
|
|
|
this.DataContext = this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private T? FindElementByName<T>(DependencyObject element, string sChildName) where T : FrameworkElement {
|
|
|
|
|
T? childElement = null;
|
|
|
|
|
var nChildCount = VisualTreeHelper.GetChildrenCount(element);
|
|
|
|
|
for (int i = 0; i < nChildCount; i++) {
|
|
|
|
|
if (!(VisualTreeHelper.GetChild(element, i) is FrameworkElement child)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (child is T t && child.Name.Equals(sChildName)) {
|
|
|
|
|
childElement = t;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
childElement = this.FindElementByName<T>(child, sChildName);
|
|
|
|
|
|
|
|
|
|
if (childElement != null) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return childElement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ClearAllMessages() {
|
|
|
|
|
this.Messages.Clear();
|
|
|
|
|
foreach (var tab in this.App.Config.Tabs) {
|
|
|
|
|
tab.ClearMessages();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddSystemMessage(string content) {
|
2020-11-01 15:31:56 +00:00
|
|
|
|
var message = new ServerMessage(
|
|
|
|
|
DateTime.UtcNow,
|
|
|
|
|
0,
|
|
|
|
|
new byte[0],
|
|
|
|
|
Encoding.UTF8.GetBytes(content),
|
|
|
|
|
new List<Chunk> {
|
|
|
|
|
new TextChunk(content) {
|
2020-11-01 01:31:10 +00:00
|
|
|
|
Foreground = 0xb38cffff,
|
|
|
|
|
},
|
2020-11-01 15:31:56 +00:00
|
|
|
|
}
|
|
|
|
|
);
|
2020-11-01 01:31:10 +00:00
|
|
|
|
this.AddMessage(message);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 00:48:21 +00:00
|
|
|
|
private int lastSequence = -1;
|
|
|
|
|
private int insertAt;
|
|
|
|
|
|
|
|
|
|
public void AddReversedChunk(ServerMessage[] messages, int sequence) {
|
|
|
|
|
if (sequence != this.lastSequence) {
|
|
|
|
|
this.lastSequence = sequence;
|
|
|
|
|
this.insertAt = this.Messages.Count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// detect if scroller is at the bottom
|
|
|
|
|
var scroller = this.FindElementByName<ScrollViewer>(this.Tabs, "scroller");
|
|
|
|
|
var wasAtBottom = Math.Abs(scroller!.VerticalOffset - scroller.ScrollableHeight) < .0001;
|
|
|
|
|
|
|
|
|
|
// add messages to main list
|
|
|
|
|
this.Messages.InsertRange(this.insertAt, messages);
|
|
|
|
|
// add message to each tab if the filter allows for it
|
|
|
|
|
foreach (var tab in this.App.Config.Tabs) {
|
2020-11-11 23:05:05 +00:00
|
|
|
|
tab.AddReversedChunk(messages, sequence, this.App.Config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var diff = this.Messages.Count - this.App.Config.LocalBacklogMessages;
|
|
|
|
|
if (diff > 0) {
|
|
|
|
|
this.Messages.RemoveRange(0, (int)diff);
|
2020-11-06 00:48:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// scroll to the bottom if previously at the bottom
|
|
|
|
|
if (wasAtBottom) {
|
|
|
|
|
scroller.ScrollToBottom();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-01 01:31:10 +00:00
|
|
|
|
public void AddMessage(ServerMessage message) {
|
|
|
|
|
// detect if scroller is at the bottom
|
|
|
|
|
var scroller = this.FindElementByName<ScrollViewer>(this.Tabs, "scroller");
|
|
|
|
|
var wasAtBottom = Math.Abs(scroller!.VerticalOffset - scroller.ScrollableHeight) < .0001;
|
|
|
|
|
|
|
|
|
|
// add message to main list
|
2020-11-06 00:48:21 +00:00
|
|
|
|
this.Messages.Add(message);
|
2020-11-01 01:31:10 +00:00
|
|
|
|
// add message to each tab if the filter allows for it
|
|
|
|
|
foreach (var tab in this.App.Config.Tabs) {
|
2020-11-11 23:05:05 +00:00
|
|
|
|
tab.AddMessage(message, this.App.Config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var diff = this.Messages.Count - this.App.Config.LocalBacklogMessages;
|
|
|
|
|
if (diff > 0) {
|
|
|
|
|
this.Messages.RemoveRange(0, (int)diff);
|
2020-11-01 01:31:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// scroll to the bottom if previously at the bottom
|
|
|
|
|
if (wasAtBottom) {
|
|
|
|
|
scroller.ScrollToBottom();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Connect_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
var dialog = new ConnectDialog {
|
|
|
|
|
Owner = this,
|
|
|
|
|
};
|
|
|
|
|
dialog.ShowDialog();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Disconnect_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
this.App.Disconnect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Input_Submit(object sender, KeyEventArgs e) {
|
|
|
|
|
if (e.Key != Key.Return) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var conn = this.App.Connection;
|
|
|
|
|
if (conn == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(sender is TextBox)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var textBox = (TextBox)sender;
|
|
|
|
|
|
|
|
|
|
conn.SendMessage(textBox.Text);
|
|
|
|
|
textBox.Text = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Configuration_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
new ConfigWindow(this, this.App.Config).Show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Tabs_Loaded(object sender, RoutedEventArgs e) {
|
|
|
|
|
this.Tabs.SelectedIndex = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Tabs_SelectionChanged(object sender, SelectionChangedEventArgs e) {
|
|
|
|
|
var scroller = this.FindElementByName<ScrollViewer>(this.Tabs, "scroller");
|
|
|
|
|
scroller?.ScrollToBottom();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ManageTabs_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
new ManageTabs(this).Show();
|
2020-10-23 21:24:32 +00:00
|
|
|
|
}
|
2020-11-06 20:19:42 +00:00
|
|
|
|
|
|
|
|
|
private void Scan_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
new ServerScan(this).Show();
|
|
|
|
|
}
|
2020-11-08 01:10:29 +00:00
|
|
|
|
|
|
|
|
|
public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
|
|
|
|
|
|
|
internal virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) {
|
|
|
|
|
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
|
|
}
|
2020-11-11 02:56:04 +00:00
|
|
|
|
|
|
|
|
|
private void Export_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
new Export(this).Show();
|
|
|
|
|
}
|
2020-11-12 02:25:59 +00:00
|
|
|
|
|
|
|
|
|
private void Licence_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
new LicenceWindow(this, false).Show();
|
|
|
|
|
}
|
2020-11-13 02:18:49 +00:00
|
|
|
|
|
|
|
|
|
private void Exit_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
this.Close();
|
|
|
|
|
this.App.Shutdown();
|
|
|
|
|
}
|
2020-10-23 21:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|