Merge branch 'ConnectionController'
This commit is contained in:
82
PolyChat/Assets/polychat_logo.svg
Normal file
82
PolyChat/Assets/polychat_logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 12 KiB |
211
PolyChat/Controller.cs
Normal file
211
PolyChat/Controller.cs
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using SocketIOSharp.Server;
|
||||||
|
using SocketIOSharp.Server.Client;
|
||||||
|
using PolyChat.Models;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PolyChat
|
||||||
|
{
|
||||||
|
// 10.1.211.26 Marc
|
||||||
|
// 10.1.218.90 Felix
|
||||||
|
// 10.4.141.77 Pat
|
||||||
|
class Controller
|
||||||
|
{
|
||||||
|
// Constants
|
||||||
|
private const ushort PORT = 8050;
|
||||||
|
// Controller
|
||||||
|
private readonly MainPage UIController;
|
||||||
|
private readonly FileManager fileManager;
|
||||||
|
// Props
|
||||||
|
private Dictionary<string, Connection> Connections = new Dictionary<string, Connection>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes Controller with UI access
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uiController">UWP UI Controller</param>
|
||||||
|
public Controller(MainPage uiController)
|
||||||
|
{
|
||||||
|
UIController = uiController;
|
||||||
|
fileManager = new FileManager(this);
|
||||||
|
fileManager.loadChats();
|
||||||
|
Serve();
|
||||||
|
|
||||||
|
// test
|
||||||
|
/*
|
||||||
|
UIController.OnIncomingConnection("localhost");
|
||||||
|
UIController.OnIncomingConnection("1.2.3.4");
|
||||||
|
UIController.OnIncomingConnection("1.2.4.8");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Connect(string ip)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Controller.Connect ---");
|
||||||
|
if (isInConnections(ip))
|
||||||
|
{
|
||||||
|
Debug.WriteLine("---- We have an active connection to this client. ABORT! ----");
|
||||||
|
CloseChatUI(ip);
|
||||||
|
//Todo show error!
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Connections.Add(ip, new Connection(ip, PORT, Data => OnMessage(ip, Data), CloseChat));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// starts server for clients to connect to
|
||||||
|
/// </summary>
|
||||||
|
private void Serve()
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Controller.Serve ---");
|
||||||
|
SocketIOServer server = new SocketIOServer(new SocketIOServerOption(PORT));
|
||||||
|
server.Start();
|
||||||
|
Debug.WriteLine("Port " + server.Option.Port);
|
||||||
|
Debug.WriteLine("Path " + server.Option.Path);
|
||||||
|
// listen for connection
|
||||||
|
server.OnConnection((SocketIOSocket socket) =>
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Client connected! ---");
|
||||||
|
// setup event listeners
|
||||||
|
socket.On("initial", (JToken[] data) =>
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- initial packet received ---");
|
||||||
|
string ForeignIp = data[0].ToString();
|
||||||
|
|
||||||
|
Debug.WriteLine($"--- this ip was in the inital packet: {ForeignIp} ---");
|
||||||
|
if (isInConnections(ForeignIp))
|
||||||
|
{
|
||||||
|
Debug.WriteLine("---- We have an active connection to this client. ABORT! ----");//Todo show error!
|
||||||
|
CloseChatUI(ForeignIp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.WriteLine("---- Added new Connection ----");
|
||||||
|
Connections.Add(ForeignIp, new Connection(socket, Data => OnMessage(ForeignIp, Data), CloseChat));
|
||||||
|
UIController.OnIncomingConnection(ForeignIp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendBroadcastMessage(string type, string content)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Controller.Broadcast ---");
|
||||||
|
foreach (KeyValuePair<string, Connection> entry in Connections)
|
||||||
|
{
|
||||||
|
SendMessage(entry.Key, type, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends message to given ip
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="content"></param>
|
||||||
|
public void SendMessage(string ip, string type, string content)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Controller.SendMessage ---");
|
||||||
|
Debug.WriteLine($"{type} -> {ip} content: {content}");
|
||||||
|
JObject json = new JObject(
|
||||||
|
new JProperty("type", type),
|
||||||
|
new JProperty("content", content)
|
||||||
|
);
|
||||||
|
Debug.WriteLine($"json: {json.ToString()}");
|
||||||
|
// send as json
|
||||||
|
Connections[ip].SendMessage(json.ToString());
|
||||||
|
// save to logs
|
||||||
|
fileManager.saveChats(ip, json.ToString(), DateTime.Now);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if We recieve a message this method gets triggert
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip from sender</param>
|
||||||
|
/// <param name="data">String that is send</param>
|
||||||
|
private void OnMessage(string ip, JToken[] data)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Controller.OnMessage ---");
|
||||||
|
if (data != null && data.Length > 0 && data[0] != null)
|
||||||
|
{
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
Debug.WriteLine("RAW: " + data[0]);
|
||||||
|
UIController.OnIncomingMessage(ip, data[0].ToString(), now);
|
||||||
|
fileManager.saveChats(ip, data[0].ToString(), now);
|
||||||
|
}
|
||||||
|
else Debug.WriteLine("Undefined: " + data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes chat connection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="IP">ip of user to be closed</param>
|
||||||
|
/// <param name="wasConnected"></param>
|
||||||
|
/// <param name="delete"></param>
|
||||||
|
public void CloseChat(string IP, bool wasConnected = true, bool delete = false)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Deleting connection with IP:{IP}");
|
||||||
|
if (IP != null && Connections.ContainsKey(IP))
|
||||||
|
{
|
||||||
|
Connections[IP].Close();
|
||||||
|
Connections.Remove(IP);
|
||||||
|
}
|
||||||
|
if (delete || !wasConnected)
|
||||||
|
CloseChatUI(IP, wasConnected, delete);
|
||||||
|
if (delete)
|
||||||
|
fileManager.deleteChat(IP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sends incoming message to ui
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">ip of client that send the message</param>
|
||||||
|
/// <param name="jsonArr">the json array that is ti be displayed in th gui</param>
|
||||||
|
public void SendIncomingMessageUI(String ip, String jsonArr)
|
||||||
|
{
|
||||||
|
UIController.OnIncomingConnection(ip);
|
||||||
|
UIController.OnIncomingMessages(ip, jsonArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseChatUI(string IP, bool wasConnected = true, bool delete = false)
|
||||||
|
{
|
||||||
|
UIController.OnChatPartnerDeleted(IP);
|
||||||
|
string heading = wasConnected ? "Connection Closed" : "Connection Failed";
|
||||||
|
if(!delete)
|
||||||
|
UIController.ShowConnectionError(IP, heading, $"Connecting to {IP} failed...");
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool isInConnections(string IP)
|
||||||
|
{
|
||||||
|
return Connections.ContainsKey(IP);
|
||||||
|
}
|
||||||
|
public bool IsConnected(string ip)
|
||||||
|
{
|
||||||
|
return Connections.ContainsKey(ip) && Connections[ip].IsConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// returns your own ip that starts with 10. becuase that is our subnet
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string getIP()
|
||||||
|
{
|
||||||
|
IPHostEntry ipEntry = Dns.GetHostEntry(Dns.GetHostName());
|
||||||
|
IPAddress[] addrList = ipEntry.AddressList;
|
||||||
|
for (short i = 0; i < addrList.Length; i++)
|
||||||
|
{
|
||||||
|
if (addrList[i].ToString().Substring(0, 3).Equals("10."))
|
||||||
|
{
|
||||||
|
return addrList[i].ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,10 +13,11 @@
|
|||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<!-- LEFT SIDE -->
|
<!-- LEFT SIDE -->
|
||||||
<Grid Grid.Column="0" Margin="16">
|
<Grid Grid.Column="0" Padding="16" Background="{ThemeResource SystemChromeMediumColor}">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<!-- CONNECTION HEADER -->
|
<!-- CONNECTION HEADER -->
|
||||||
<StackPanel HorizontalAlignment="Stretch" Spacing="8" Margin="0 0 0 8">
|
<StackPanel HorizontalAlignment="Stretch" Spacing="8" Margin="0 0 0 8">
|
||||||
@@ -37,7 +38,7 @@
|
|||||||
<TextBlock Text="Connect to" Foreground="{ThemeResource SystemColorDisabledTextColor}"/>
|
<TextBlock Text="Connect to" Foreground="{ThemeResource SystemColorDisabledTextColor}"/>
|
||||||
<TextBlock x:Name="ipAddress" Grid.Column="1"/>
|
<TextBlock x:Name="ipAddress" Grid.Column="1"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Border BorderThickness="1" BorderBrush="{ThemeResource AppBarBorderThemeBrush}"/>
|
<Border BorderThickness="1" BorderBrush="{ThemeResource SystemControlBackgroundListLowBrush}"/>
|
||||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
@@ -53,14 +54,10 @@
|
|||||||
<ListView x:Name="listViewPartners" ItemsSource="{x:Bind Partners}" HorizontalAlignment="Stretch" Margin="0 8 0 0">
|
<ListView x:Name="listViewPartners" ItemsSource="{x:Bind Partners}" HorizontalAlignment="Stretch" Margin="0 8 0 0">
|
||||||
<ListView.ItemTemplate>
|
<ListView.ItemTemplate>
|
||||||
<DataTemplate x:DataType="models:ChatPartner">
|
<DataTemplate x:DataType="models:ChatPartner">
|
||||||
<RadioButton GroupName="chatSelect" Tag="{x:Bind Code}" HorizontalAlignment="Stretch" Height="64" Checked="OnChatPartnerSelected">
|
<RadioButton GroupName="chatSelect" Tag="{x:Bind Code}" HorizontalAlignment="Stretch" Height="64" Click="OnChatPartnerSelected">
|
||||||
<StackPanel x:Name="ChatPartner" VerticalAlignment="Center" HorizontalAlignment="Stretch">
|
<StackPanel x:Name="ChatPartner" VerticalAlignment="Center" HorizontalAlignment="Stretch">
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
|
<TextBlock HorizontalAlignment="Stretch" Text="{x:Bind Name}"/>
|
||||||
<TextBlock HorizontalAlignment="Stretch" Text="{x:Bind Name}"/>
|
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text="{x:Bind Code}"/>
|
||||||
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text=" ("/>
|
|
||||||
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text="{x:Bind Code}"/>
|
|
||||||
<TextBlock Foreground="{ThemeResource SystemColorDisabledTextColor}" Text=")"/>
|
|
||||||
</StackPanel>
|
|
||||||
<!--
|
<!--
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
|
||||||
<TextBlock HorizontalAlignment="Stretch" Text="{x:Bind Messages.Last().toString()}"/>
|
<TextBlock HorizontalAlignment="Stretch" Text="{x:Bind Messages.Last().toString()}"/>
|
||||||
@@ -73,6 +70,7 @@
|
|||||||
</ListView.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
</ListView>
|
</ListView>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
<Button Grid.Row="2" Click="OnToggleTheme" Content="Toggle Theme"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<TextBlock x:Name="textNoChatSelected" Grid.Column="1" Text="No Chat Selected" Foreground="{ThemeResource SystemColorDisabledTextColor}" FontSize="24" VerticalAlignment="Center" HorizontalAlignment="Center"/>
|
<TextBlock x:Name="textNoChatSelected" Grid.Column="1" Text="No Chat Selected" Foreground="{ThemeResource SystemColorDisabledTextColor}" FontSize="24" VerticalAlignment="Center" HorizontalAlignment="Center"/>
|
||||||
<!-- RIGHT SIDE -->
|
<!-- RIGHT SIDE -->
|
||||||
@@ -97,13 +95,17 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
<!-- CHAT -->
|
<!-- CHAT -->
|
||||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
|
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
|
||||||
<ListView x:Name="listViewMessages" VerticalAlignment="Bottom" Margin="4 16">
|
<ListView x:Name="listViewMessages" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="4 16">
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListViewItem">
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
<ListView.ItemTemplate>
|
<ListView.ItemTemplate>
|
||||||
<DataTemplate x:DataType="models:Message">
|
<DataTemplate x:DataType="models:ChatMessage">
|
||||||
<StackPanel x:Name="Message" Margin="0 4" Padding="16 8" CornerRadius="4" Background="{ThemeResource SystemAccentColor}">
|
<StackPanel HorizontalAlignment="{x:Bind Align}" x:Name="Message" MaxWidth="320" Margin="0 4" Padding="16 8" CornerRadius="4" Background="{ThemeResource SystemAccentColor}">
|
||||||
<TextBlock Text="{x:Bind Msg}"/>
|
<TextBlock Text="{x:Bind Content}" Foreground="{ThemeResource SystemAltHighColor}" TextWrapping="WrapWholeWords" FontSize="14"/>
|
||||||
<TextBlock Text="{x:Bind Timestamp.ToShortDateString()}"/>
|
<TextBlock Text="{x:Bind TimeStamp.ToString()}" Foreground="{ThemeResource SystemAltMediumColor}"/>
|
||||||
<TextBlock Text="{x:Bind Foreign}"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
using PolyChat.Models;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using PolyChat.Models;
|
||||||
using PolyChat.Util;
|
using PolyChat.Util;
|
||||||
using PolyChat.Views;
|
using PolyChat.Views;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Text.Json;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.UI.Core;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
||||||
|
|
||||||
@@ -17,63 +22,90 @@ namespace PolyChat
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class MainPage : Page
|
public sealed partial class MainPage : Page
|
||||||
{
|
{
|
||||||
private NetworkingController networkingController;
|
private Controller Controller;
|
||||||
private ObservableCollection<ChatPartner> Partners;
|
private ObservableCollection<ChatPartner> Partners;
|
||||||
private ChatPartner selectedPartner = null;
|
private ChatPartner selectedPartner = null;
|
||||||
private string username;
|
private string username;
|
||||||
|
private static ElementTheme Theme = ElementTheme.Light;
|
||||||
|
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
// init controller
|
// init controller
|
||||||
networkingController = new NetworkingController(this);
|
Controller = new Controller(this);
|
||||||
// ui variables
|
// ui variables
|
||||||
ipAddress.Text = IP.GetCodeFromIP(networkingController.getIP().ToString());
|
ipAddress.Text = IP.GetCodeFromIP(Controller.getIP());
|
||||||
Partners = new ObservableCollection<ChatPartner>();
|
Partners = new ObservableCollection<ChatPartner>();
|
||||||
|
// theming
|
||||||
|
RequestedTheme = Theme;
|
||||||
|
// updated placeholder
|
||||||
updateNoChatsPlaceholder();
|
updateNoChatsPlaceholder();
|
||||||
updateNoUsernamePlaceholder();
|
updateNoUsernamePlaceholder();
|
||||||
updateNoChatSelected();
|
updateNoChatSelected();
|
||||||
updateSendButtonEnabled();
|
updateSendButtonEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void ShowConnectionError(string message)
|
public async void ShowConnectionError(string param, string heading, string message)
|
||||||
{
|
{
|
||||||
ConnectionFailedDialog dialog = new ConnectionFailedDialog(message);
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||||
var result = await dialog.ShowAsync();
|
|
||||||
if (result == ContentDialogResult.Primary)
|
|
||||||
{
|
{
|
||||||
//retry
|
Dialog dialog = new Dialog(
|
||||||
}
|
Dialog.TYPE_ERROR,
|
||||||
// else abort -> del chat
|
heading,
|
||||||
|
message,
|
||||||
|
new DialogButton(
|
||||||
|
"Retry",
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
Controller.Connect(param);
|
||||||
|
Partners.Add(new ChatPartner(
|
||||||
|
"Connecting...",
|
||||||
|
param
|
||||||
|
));
|
||||||
|
updateNoChatsPlaceholder();
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new DialogButton(
|
||||||
|
"Ignore",
|
||||||
|
() => { /* do nothing */ }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
SafelyOpenDialog(dialog);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// EVENTS
|
// EVENTS
|
||||||
|
|
||||||
public void OnChatPartnerSelected(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
string code = ((RadioButton)sender).Tag.ToString();
|
|
||||||
selectedPartner = Partners.First(p => p.Code == code);
|
|
||||||
listViewMessages.ItemsSource = selectedPartner.Messages;
|
|
||||||
selectedPartnerName.Text = selectedPartner.Name;
|
|
||||||
updateNoChatSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSendMessage(object sender = null, RoutedEventArgs e = null)
|
public void OnSendMessage(object sender = null, RoutedEventArgs e = null)
|
||||||
{
|
{
|
||||||
selectedPartner.AddMessage(new Message(inputSend.Text,false));
|
selectedPartner.AddMessage(new ChatMessage(username, "message", inputSend.Text, DateTime.Now, false));
|
||||||
networkingController.sendMessage(selectedPartner.Code, inputSend.Text);
|
Controller.SendMessage(selectedPartner.Code, "message", inputSend.Text);
|
||||||
// clear input
|
// clear input
|
||||||
inputSend.Text = "";
|
inputSend.Text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void OnOpenNewChatDialog(object sender = null, RoutedEventArgs e = null)
|
public async void OnOpenNewChatDialog(object sender = null, RoutedEventArgs e = null)
|
||||||
{
|
{
|
||||||
|
// test
|
||||||
|
/*
|
||||||
|
OnIncomingMessage(
|
||||||
|
"localhost",
|
||||||
|
new JObject(
|
||||||
|
new JProperty("type", "message"),
|
||||||
|
new JProperty("content", "Test")
|
||||||
|
).ToString(),
|
||||||
|
DateTime.Now
|
||||||
|
);
|
||||||
|
*/
|
||||||
NewChatDialog dialog = new NewChatDialog();
|
NewChatDialog dialog = new NewChatDialog();
|
||||||
var result = await dialog.ShowAsync();
|
var result = await SafelyOpenDialog(dialog);
|
||||||
if (result == ContentDialogResult.Primary)
|
if (result == ContentDialogResult.Primary)
|
||||||
{
|
{
|
||||||
string ip = IP.GetIPfromCode(dialog.getValue());
|
string ip = IP.GetIPFromCode(dialog.getValue());
|
||||||
networkingController.connectNewClient(ip);
|
Controller.Connect(ip);
|
||||||
Partners.Add(new ChatPartner(
|
ChatPartner pa = Partners.FirstOrDefault(p => p.Code == ip);
|
||||||
|
if (pa == null)
|
||||||
|
Partners.Add(new ChatPartner(
|
||||||
"Connecting...",
|
"Connecting...",
|
||||||
ip
|
ip
|
||||||
));
|
));
|
||||||
@@ -84,41 +116,133 @@ namespace PolyChat
|
|||||||
public async void OnOpenEditUsernameDialog(object sender = null, RoutedEventArgs e = null)
|
public async void OnOpenEditUsernameDialog(object sender = null, RoutedEventArgs e = null)
|
||||||
{
|
{
|
||||||
EditUsernameDialog dialog = new EditUsernameDialog(username);
|
EditUsernameDialog dialog = new EditUsernameDialog(username);
|
||||||
var result = await dialog.ShowAsync();
|
var result = await SafelyOpenDialog(dialog);
|
||||||
if (result == ContentDialogResult.Primary)
|
if (result == ContentDialogResult.Primary)
|
||||||
{
|
{
|
||||||
username = dialog.getValue();
|
username = dialog.getValue();
|
||||||
if (username.Length == 0) textUsername.Text = "Unknown";
|
textUsername.Text = username;
|
||||||
else textUsername.Text = username;
|
Controller.SendBroadcastMessage("username", username);
|
||||||
}
|
}
|
||||||
updateNoUsernamePlaceholder();
|
updateNoUsernamePlaceholder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnIncomingMessage(Message message)
|
/// <summary>
|
||||||
|
/// Adds a new ChatPartner to the UI with default Name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">IP Adress, gets shown as Util.IP > Code</param>
|
||||||
|
public async void OnIncomingConnection(string ip)
|
||||||
{
|
{
|
||||||
ChatPartner sendingPartner = Partners.First(p => p.Code == message.Ip);
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||||
sendingPartner.AddMessage(new Message(
|
{
|
||||||
message.Msg,
|
Partners.Add(new ChatPartner(
|
||||||
true,
|
"Connecting...",
|
||||||
message.Sender
|
ip
|
||||||
));
|
));
|
||||||
|
updateNoChatsPlaceholder();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an message to the UI, based on .sender if known
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">ChatMessage</param>
|
||||||
|
public async void OnIncomingMessage(string origin, string json, DateTime timeStamp)
|
||||||
|
{
|
||||||
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||||
|
{
|
||||||
|
var doc = JsonDocument.Parse(json).RootElement;
|
||||||
|
string type = doc.GetProperty("type").GetString();
|
||||||
|
string content = doc.GetProperty("content").GetString();
|
||||||
|
ChatPartner sendingPartner = Partners.FirstOrDefault(p => p.Code == origin);
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "username":
|
||||||
|
Debug.WriteLine($"! username change for {sendingPartner.Code} -> {content}");
|
||||||
|
sendingPartner.Name = content;
|
||||||
|
int index = Partners.IndexOf(sendingPartner);
|
||||||
|
Partners.Remove(sendingPartner);
|
||||||
|
Partners.Insert(index, sendingPartner);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sendingPartner.AddMessage(new ChatMessage(origin, type, content, timeStamp, true));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public async void OnIncomingMessages(string origin, string json)
|
||||||
|
{
|
||||||
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||||
|
{
|
||||||
|
ChatPartner sendingPartner = Partners.FirstOrDefault(p => p.Code == origin);
|
||||||
|
JArray arr = JArray.Parse(json);
|
||||||
|
foreach (JObject item in arr)
|
||||||
|
{
|
||||||
|
sendingPartner.AddMessage(
|
||||||
|
new ChatMessage(
|
||||||
|
origin,
|
||||||
|
item["type"].ToString(),
|
||||||
|
item["content"].ToString(),
|
||||||
|
DateTime.Parse(item["timestamp"].ToString()),
|
||||||
|
false // TODO: FIX !!!!
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDeleteChat(object sender = null, RoutedEventArgs e = null)
|
private void OnDeleteChat(object sender = null, RoutedEventArgs e = null)
|
||||||
{
|
{
|
||||||
|
Controller.CloseChat(selectedPartner.Code,delete: true);
|
||||||
Partners.Remove(selectedPartner);
|
Partners.Remove(selectedPartner);
|
||||||
updateNoChatsPlaceholder();
|
updateNoChatsPlaceholder();
|
||||||
|
updateNoChatSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void OnChatPartnerDeleted(string code)
|
||||||
|
{
|
||||||
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||||
|
{
|
||||||
|
Partners.Remove(Partners.FirstOrDefault(p => p.Code.Equals(code)));
|
||||||
|
selectedPartner = null;
|
||||||
|
updateNoChatsPlaceholder();
|
||||||
|
updateNoChatSelected();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void OnChatPartnerSelected(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
string code = ((RadioButton)sender).Tag.ToString();
|
||||||
|
selectedPartner = Partners.FirstOrDefault(p => p.Code == code);
|
||||||
|
listViewMessages.ItemsSource = selectedPartner.Messages;
|
||||||
|
selectedPartnerName.Text = selectedPartner.Name;
|
||||||
|
updateNoChatSelected();
|
||||||
|
if (!Controller.IsConnected(code)) Controller.Connect(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnToggleTheme(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Theme = Theme == ElementTheme.Light ? ElementTheme.Dark : ElementTheme.Light;
|
||||||
|
RequestedTheme = Theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnKeyUp(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
|
private void OnKeyUp(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
updateSendButtonEnabled();
|
updateSendButtonEnabled();
|
||||||
if (e.Key == Windows.System.VirtualKey.Enter)
|
if (buttonSend.IsEnabled && e.Key == Windows.System.VirtualKey.Enter)
|
||||||
{
|
{
|
||||||
OnSendMessage();
|
OnSendMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IAsyncOperation<ContentDialogResult> SafelyOpenDialog(ContentDialog d)
|
||||||
|
{
|
||||||
|
if(VisualTreeHelper.GetOpenPopups(Window.Current).Count == 0)
|
||||||
|
return d.ShowAsync();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GETTERS
|
||||||
|
|
||||||
|
public static ElementTheme GetTheme() => Theme;
|
||||||
|
|
||||||
// UPDATE FUNCTIONS FOR UI PLACEHOLDERS
|
// UPDATE FUNCTIONS FOR UI PLACEHOLDERS
|
||||||
|
|
||||||
private void updateNoChatsPlaceholder()
|
private void updateNoChatsPlaceholder()
|
||||||
|
|||||||
@@ -1,29 +1,42 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
|
||||||
namespace PolyChat.Models
|
namespace PolyChat.Models
|
||||||
{
|
{
|
||||||
public class ChatMessage
|
public class ChatMessage
|
||||||
{
|
{
|
||||||
public readonly string Sender;
|
public string Origin;
|
||||||
public readonly DateTime Timestamp = new DateTime(1970, 01, 01);
|
public string Type;
|
||||||
public readonly string Content;
|
public string Content;
|
||||||
public readonly string Ip;
|
public DateTime TimeStamp;
|
||||||
public readonly bool Foreign;
|
public HorizontalAlignment Align;
|
||||||
|
private bool Foreign;
|
||||||
|
|
||||||
public ChatMessage(string Content = "", bool Foreign = true, string Sender= "Unknown", string Ip = "127.0.0.1")
|
/// <summary>
|
||||||
|
/// Create Message
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="origin">Origin IP</param>
|
||||||
|
/// <param name="type">Message Type, usually "message"</param>
|
||||||
|
/// <param name="content">Message Content, usually plain text</param>
|
||||||
|
/// <param name="timeStamp">Parsed DateTime</param>
|
||||||
|
public ChatMessage(string origin, string type, string content, DateTime timeStamp, bool foreign)
|
||||||
{
|
{
|
||||||
this.Sender = Sender;
|
Origin = origin;
|
||||||
this.Timestamp = DateTime.Now;
|
TimeStamp = timeStamp;
|
||||||
this.Content = Content;
|
Type = type;
|
||||||
this.Foreign = Foreign;
|
Content = content;
|
||||||
this.Ip = Ip;
|
Align = foreign ? HorizontalAlignment.Right : HorizontalAlignment.Left;
|
||||||
|
Foreign = foreign;
|
||||||
|
Debug.WriteLine("Created Loaded Message: " + ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
override
|
override
|
||||||
public string ToString()
|
public string ToString()
|
||||||
{
|
{
|
||||||
string prefix = Foreign ? "Other" : "Me";
|
string prefix = Foreign ? "Other" : "Me";
|
||||||
return $"{prefix}: {Content}({Sender})";
|
return $"{Type} from {prefix}: {Content}({Origin})";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using SocketIOSharp.Server.Client;
|
using SocketIOSharp.Server.Client;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace PolyChat.Models
|
namespace PolyChat.Models
|
||||||
{
|
{
|
||||||
@@ -7,20 +10,20 @@ namespace PolyChat.Models
|
|||||||
{
|
{
|
||||||
public string Name;
|
public string Name;
|
||||||
public string Code;
|
public string Code;
|
||||||
public ObservableCollection<Message> Messages;
|
public ObservableCollection<ChatMessage> Messages;
|
||||||
private SocketIOSocket socketIOSocket;
|
private SocketIOSocket socketIOSocket;
|
||||||
|
|
||||||
public ChatPartner(string name, string code, ObservableCollection<Message> messages = null)
|
public ChatPartner(string name, string code, ObservableCollection<ChatMessage> messages = null)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Code = code;
|
Code = code;
|
||||||
if (messages == null) Messages = new ObservableCollection<Message>();
|
if (messages == null) Messages = new ObservableCollection<ChatMessage>();
|
||||||
else Messages = messages;
|
else Messages = messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SocketIOSocket SocketIOSocket { get => socketIOSocket; set => socketIOSocket = value; }
|
public SocketIOSocket SocketIOSocket { get => socketIOSocket; set => socketIOSocket = value; }
|
||||||
|
|
||||||
public void AddMessage(Message message)
|
public void AddMessage(ChatMessage message)
|
||||||
{
|
{
|
||||||
Messages.Add(message);
|
Messages.Add(message);
|
||||||
}
|
}
|
||||||
|
|||||||
101
PolyChat/Models/Connection.cs
Normal file
101
PolyChat/Models/Connection.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using EngineIOSharp.Common.Enum;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using SocketIOSharp.Client;
|
||||||
|
using SocketIOSharp.Common;
|
||||||
|
using SocketIOSharp.Server.Client;
|
||||||
|
using PolyChat.Models;
|
||||||
|
|
||||||
|
namespace PolyChat.Models
|
||||||
|
{
|
||||||
|
public class Connection
|
||||||
|
{
|
||||||
|
private SocketIOClient Client;
|
||||||
|
private SocketIOSocket Socket;
|
||||||
|
private bool Connected = false;
|
||||||
|
private readonly string IP;
|
||||||
|
private Action<string, bool, bool> DeleteConnection;
|
||||||
|
|
||||||
|
public Connection(string ip, ushort port, Action<JToken[]> onMessage, Action<string, bool, bool> onClose)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("! CONNECTING TO SERVER !");
|
||||||
|
IP = ip;
|
||||||
|
DeleteConnection = onClose;
|
||||||
|
// establish connection
|
||||||
|
Client = new SocketIOClient(new SocketIOClientOption(EngineIOScheme.http, ip, port));
|
||||||
|
Client.Connect();
|
||||||
|
// setup event listeners
|
||||||
|
Client.On(SocketIOEvent.CONNECTION, OnConnect);
|
||||||
|
Client.On(SocketIOEvent.DISCONNECT, OnDisconnect);
|
||||||
|
Client.On(SocketIOEvent.ERROR, (JToken[] Data) => OnError(Data));
|
||||||
|
Client.On("message", (Action<JToken[]>) onMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection(SocketIOSocket socket, Action<JToken[]> onMessage, Action<string, bool, bool> onClose)
|
||||||
|
{
|
||||||
|
Socket = socket;
|
||||||
|
DeleteConnection = onClose;
|
||||||
|
Socket.On(SocketIOEvent.DISCONNECT, OnDisconnect);
|
||||||
|
Socket.On(SocketIOEvent.ERROR, (JToken[] Data) => OnError(Data));
|
||||||
|
Socket.On("message", (Action<JToken[]>) onMessage);
|
||||||
|
|
||||||
|
//we are connected if we got here, inital packet was already received
|
||||||
|
Connected = true;
|
||||||
|
}
|
||||||
|
public void SendMessage(string message)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Sending message ---");
|
||||||
|
Debug.WriteLine($"Connected {Connected}");
|
||||||
|
Debug.WriteLine($"Client {Client}");
|
||||||
|
Debug.WriteLine($"Socket {Socket}");
|
||||||
|
if (Socket != null) Socket.Emit("message", message);
|
||||||
|
else if (Client != null) Client.Emit("message", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event Methods
|
||||||
|
|
||||||
|
private void OnConnect()
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Sending initial packet to server ---");
|
||||||
|
Client.Emit("initial", Controller.getIP());
|
||||||
|
Debug.WriteLine("--- Connection successfull ---");
|
||||||
|
Connected = true;
|
||||||
|
}
|
||||||
|
private void OnDisconnect()
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Disconnected! ---");
|
||||||
|
Debug.WriteLine($"--- Deleting Connection with IP: {IP}---");
|
||||||
|
DeleteConnection(IP, IsConnected(),false);
|
||||||
|
Connected = false;
|
||||||
|
}
|
||||||
|
private void OnError(JToken[] data)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--- Error: ---");
|
||||||
|
if (data != null && data.Length > 0 && data[0] != null)
|
||||||
|
Debug.WriteLine(data[0]);
|
||||||
|
else
|
||||||
|
Debug.WriteLine("Unkown Error");
|
||||||
|
Debug.WriteLine("---");
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (Client != null) Client.Close();
|
||||||
|
if (Socket != null) Socket.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsConnected()
|
||||||
|
{
|
||||||
|
return Connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string getIP()
|
||||||
|
{
|
||||||
|
return IP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
PolyChat/Models/DialogButton.cs
Normal file
20
PolyChat/Models/DialogButton.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PolyChat.Models
|
||||||
|
{
|
||||||
|
public class DialogButton
|
||||||
|
{
|
||||||
|
public string Text;
|
||||||
|
public Action Action;
|
||||||
|
|
||||||
|
public DialogButton(string text, Action action)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
Action = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
258
PolyChat/Models/FileManager.cs
Normal file
258
PolyChat/Models/FileManager.cs
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace PolyChat.Models
|
||||||
|
{
|
||||||
|
class FileManager
|
||||||
|
{
|
||||||
|
// Controller
|
||||||
|
private readonly Controller controller;
|
||||||
|
|
||||||
|
|
||||||
|
//===============================================================================================================================================
|
||||||
|
//Constructor
|
||||||
|
//===============================================================================================================================================
|
||||||
|
public FileManager(Controller controller)
|
||||||
|
{
|
||||||
|
this.controller = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===============================================================================================================================================
|
||||||
|
// editing save files
|
||||||
|
//===============================================================================================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// deletes chatlog of one speciffic user
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip"></param>
|
||||||
|
public void deleteChat(String ip)
|
||||||
|
{
|
||||||
|
if (Directory.Exists("U:\\PolyChat\\Saves"))
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--Path exists.--");
|
||||||
|
//go through all files and send ip and json array to ui
|
||||||
|
String[] filepaths = Directory.GetFiles("U:\\PolyChat\\Saves");
|
||||||
|
if (filepaths.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (String path in filepaths)
|
||||||
|
{
|
||||||
|
if (Path.GetFileName(path).Equals(ip+".txt"))
|
||||||
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// loads one chatlog probably when someone tries to connect
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip"></param>
|
||||||
|
public void loadChat(String ip)
|
||||||
|
{
|
||||||
|
//load dir and create if non existant
|
||||||
|
if (Directory.Exists("U:\\PolyChat\\Saves"))
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--Path exists.--");
|
||||||
|
if (File.Exists($"U:\\PolyChat\\Saves\\{ip}.txt"))
|
||||||
|
{
|
||||||
|
String jsonArr = decrypt(File.ReadAllText($"U:\\PolyChat\\Saves\\{ip}.txt"));
|
||||||
|
controller.SendIncomingMessageUI(ip, jsonArr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sends chatlogs as json array to uiController with corrosponding ip
|
||||||
|
///
|
||||||
|
/// in ui when chat is clicked connection gets established
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip"></param>
|
||||||
|
public void loadChats()
|
||||||
|
{
|
||||||
|
//load dir and create if non existant
|
||||||
|
if (Directory.Exists("U:\\PolyChat\\Saves"))
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--Path exists.--");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory("U:\\PolyChat\\Saves");
|
||||||
|
Debug.WriteLine("--Path Created--.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//go through all files and send ip and json array to ui
|
||||||
|
String[] filepaths = Directory.GetFiles("U:\\PolyChat\\Saves");
|
||||||
|
if (filepaths.Length > 0)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("---Loading Saves");
|
||||||
|
foreach (String path in filepaths)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"--{path}");
|
||||||
|
String jsonArr = decrypt(File.ReadAllText(path));
|
||||||
|
String ip = Path.GetFileName(path);
|
||||||
|
ip = ip.Substring(0, ip.Length - 4);
|
||||||
|
Debug.WriteLine($"-{ip}");
|
||||||
|
Debug.WriteLine(jsonArr);
|
||||||
|
controller.SendIncomingMessageUI(ip, jsonArr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves incoming chat message to U:\PolyChat\Saves\ip.txt
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip"></param>
|
||||||
|
/// <param name="json"></param>
|
||||||
|
public void saveChats(string ip, string json, DateTime timeStamp)
|
||||||
|
{
|
||||||
|
new Thread(() =>
|
||||||
|
{
|
||||||
|
//breaking if namechange
|
||||||
|
JObject obj = JObject.Parse(json);
|
||||||
|
if (!obj["type"].ToString().Equals("username"))
|
||||||
|
{
|
||||||
|
//adding timestamp
|
||||||
|
obj.Add(new JProperty("timestamp", timeStamp));
|
||||||
|
json = obj.ToString();
|
||||||
|
|
||||||
|
if (File.Exists($"U:\\PolyChat\\Saves\\{ip}.txt"))
|
||||||
|
{
|
||||||
|
Debug.WriteLine("--File allready exists--");
|
||||||
|
|
||||||
|
//check for integraty of file
|
||||||
|
string output = decrypt(File.ReadAllText($"U:\\PolyChat\\Saves\\{ip}.txt"));
|
||||||
|
Debug.WriteLine($"---{output}---");
|
||||||
|
if (output.Substring(0, 1).Equals("[") && output.Substring(output.Length - 1, 1).Equals("]"))
|
||||||
|
{
|
||||||
|
//structure intact
|
||||||
|
//save new chat
|
||||||
|
Debug.WriteLine("--adding new chatmessage--");
|
||||||
|
output = output.Substring(0, output.Length - 1) + ", " + json + " ]"; //rip appart and put file back together
|
||||||
|
File.Delete($"U:\\PolyChat\\Saves\\{ip}.txt");
|
||||||
|
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt(output)); //encrypt and save to textfile
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//structure not intact
|
||||||
|
//redo file
|
||||||
|
Debug.WriteLine("--Structure not intact--");
|
||||||
|
Debug.WriteLine("--redoing file--");
|
||||||
|
File.Delete($"U:\\PolyChat\\Saves\\{ip}.txt");
|
||||||
|
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt($"[ {json} ]")); //encrypt and write to file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//setup file
|
||||||
|
Debug.WriteLine("--Creating new File--");
|
||||||
|
File.WriteAllText($"U:\\PolyChat\\Saves\\{ip}.txt", encrypt($"[ {json} ]"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===============================================================================================================================================
|
||||||
|
// Encryption
|
||||||
|
//===============================================================================================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// generates keypair [public, privte] (100% secure, trust me)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private String[] genKeys()
|
||||||
|
{
|
||||||
|
return new String[] {"12345678", "12345678" };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// does exactly what it says. XD
|
||||||
|
///
|
||||||
|
/// encrypts given string and returns unreadable string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toEncrypt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private String encrypt(String toEncrypt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string textToEncrypt = toEncrypt;
|
||||||
|
string ToReturn = "";
|
||||||
|
string publickey = genKeys()[0];
|
||||||
|
string secretkey = genKeys()[1];
|
||||||
|
byte[] secretkeyByte = { };
|
||||||
|
secretkeyByte = System.Text.Encoding.UTF8.GetBytes(secretkey);
|
||||||
|
byte[] publickeybyte = { };
|
||||||
|
publickeybyte = System.Text.Encoding.UTF8.GetBytes(publickey);
|
||||||
|
MemoryStream ms = null;
|
||||||
|
CryptoStream cs = null;
|
||||||
|
byte[] inputbyteArray = System.Text.Encoding.UTF8.GetBytes(textToEncrypt);
|
||||||
|
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
|
||||||
|
{
|
||||||
|
ms = new MemoryStream();
|
||||||
|
cs = new CryptoStream(ms, des.CreateEncryptor(publickeybyte, secretkeyByte), CryptoStreamMode.Write);
|
||||||
|
cs.Write(inputbyteArray, 0, inputbyteArray.Length);
|
||||||
|
cs.FlushFinalBlock();
|
||||||
|
ToReturn = Convert.ToBase64String(ms.ToArray());
|
||||||
|
}
|
||||||
|
return ToReturn;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(ex.Message, ex.InnerException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// does exactly what it says. XD
|
||||||
|
///
|
||||||
|
/// takes in unreadable string and returns infirmation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toEncrypt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private String decrypt(String toDecrypt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string textToDecrypt = toDecrypt;
|
||||||
|
string ToReturn = "";
|
||||||
|
string publickey = genKeys()[0];
|
||||||
|
string privatekey = genKeys()[1];
|
||||||
|
byte[] privatekeyByte = { };
|
||||||
|
privatekeyByte = System.Text.Encoding.UTF8.GetBytes(privatekey);
|
||||||
|
byte[] publickeybyte = { };
|
||||||
|
publickeybyte = System.Text.Encoding.UTF8.GetBytes(publickey);
|
||||||
|
MemoryStream ms = null;
|
||||||
|
CryptoStream cs = null;
|
||||||
|
byte[] inputbyteArray = new byte[textToDecrypt.Replace(" ", "+").Length];
|
||||||
|
inputbyteArray = Convert.FromBase64String(textToDecrypt.Replace(" ", "+"));
|
||||||
|
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
|
||||||
|
{
|
||||||
|
ms = new MemoryStream();
|
||||||
|
cs = new CryptoStream(ms, des.CreateDecryptor(publickeybyte, privatekeyByte), CryptoStreamMode.Write);
|
||||||
|
cs.Write(inputbyteArray, 0, inputbyteArray.Length);
|
||||||
|
cs.FlushFinalBlock();
|
||||||
|
Encoding encoding = Encoding.UTF8;
|
||||||
|
ToReturn = encoding.GetString(ms.ToArray());
|
||||||
|
}
|
||||||
|
return ToReturn;
|
||||||
|
}
|
||||||
|
catch (Exception ae)
|
||||||
|
{
|
||||||
|
throw new Exception(ae.Message, ae.InnerException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PolyChat.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// dumy class for json converter
|
|
||||||
/// </summary>
|
|
||||||
public class MSG
|
|
||||||
{
|
|
||||||
public String sender = "unknown";
|
|
||||||
public DateTime timestamp = new DateTime(2000, 01, 01);
|
|
||||||
public String msg = "empty";
|
|
||||||
public IPAddress ip = new IPAddress(new byte[] { 49,48,46,49,46,50,49,49,46,50,54 });
|
|
||||||
|
|
||||||
|
|
||||||
public MSG(IPAddress ip, String msg, DateTime timestamp)
|
|
||||||
{
|
|
||||||
this.sender = sender;
|
|
||||||
this.ip = ip;
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace PolyChat.Models
|
|
||||||
{
|
|
||||||
enum SendCode
|
|
||||||
{
|
|
||||||
Message,
|
|
||||||
Command,
|
|
||||||
NameChange,
|
|
||||||
Initial
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
<Identity
|
<Identity
|
||||||
Name="ee2ef4f2-e61b-497a-8f0e-9fa7c90234b1"
|
Name="ee2ef4f2-e61b-497a-8f0e-9fa7c90234b1"
|
||||||
Publisher="CN=HPL2FE"
|
Publisher="CN=PatrickMarcFelix"
|
||||||
Version="1.0.0.0" />
|
Version="0.1.0.0" />
|
||||||
|
|
||||||
<mp:PhoneIdentity PhoneProductId="ee2ef4f2-e61b-497a-8f0e-9fa7c90234b1" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
<mp:PhoneIdentity PhoneProductId="ee2ef4f2-e61b-497a-8f0e-9fa7c90234b1" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,15 @@
|
|||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
||||||
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
|
<AppxPackageSigningEnabled>False</AppxPackageSigningEnabled>
|
||||||
|
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||||
|
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||||
|
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||||
|
<AppxBundle>Always</AppxBundle>
|
||||||
|
<AppxBundlePlatforms>x86</AppxBundlePlatforms>
|
||||||
|
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||||
|
<PackageCertificateThumbprint>6B0D12FC4E83C6F6997C60706A04799ED44B7E56</PackageCertificateThumbprint>
|
||||||
|
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -119,20 +127,21 @@
|
|||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Models\DialogButton.cs" />
|
||||||
|
<Compile Include="Models\Connection.cs" />
|
||||||
|
<Compile Include="Controller.cs" />
|
||||||
<Compile Include="MainPage.xaml.cs">
|
<Compile Include="MainPage.xaml.cs">
|
||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Models\Message.cs" />
|
<Compile Include="Models\ChatMessage.cs" />
|
||||||
<Compile Include="Models\ChatPartner.cs" />
|
<Compile Include="Models\ChatPartner.cs" />
|
||||||
<Compile Include="Models\Exceptions\MessageTimedOutException.cs" />
|
<Compile Include="Models\Exceptions\MessageTimedOutException.cs" />
|
||||||
<Compile Include="Models\NetworkingController.cs" />
|
|
||||||
<Compile Include="Models\Client.cs" />
|
|
||||||
<Compile Include="Models\Exceptions\ConnectionFailedException.cs" />
|
<Compile Include="Models\Exceptions\ConnectionFailedException.cs" />
|
||||||
<Compile Include="Models\SendCode.cs" />
|
<Compile Include="Models\FileManager.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Util\IP.cs" />
|
<Compile Include="Util\IP.cs" />
|
||||||
<Compile Include="Views\ConnectionFailedDialog.xaml.cs">
|
<Compile Include="Views\Dialog.xaml.cs">
|
||||||
<DependentUpon>ConnectionFailedDialog.xaml</DependentUpon>
|
<DependentUpon>Dialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Views\EditUsernameDialog.xaml.cs">
|
<Compile Include="Views\EditUsernameDialog.xaml.cs">
|
||||||
<DependentUpon>EditUsernameDialog.xaml</DependentUpon>
|
<DependentUpon>EditUsernameDialog.xaml</DependentUpon>
|
||||||
@@ -165,7 +174,7 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Views\ConnectionFailedDialog.xaml">
|
<Page Include="Views\Dialog.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
@@ -185,9 +194,15 @@
|
|||||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||||
<Version>6.2.12</Version>
|
<Version>6.2.12</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="SocketIoClientDotNet">
|
||||||
|
<Version>0.9.13</Version>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="SocketIOSharp">
|
<PackageReference Include="SocketIOSharp">
|
||||||
<Version>2.0.3</Version>
|
<Version>2.0.3</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="System.Text.Json">
|
||||||
|
<Version>5.0.2</Version>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace PolyChat.Util
|
|||||||
{
|
{
|
||||||
private const string REGEX_IP = @"^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$";
|
private const string REGEX_IP = @"^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$";
|
||||||
|
|
||||||
public static string GetIPfromCode(string code)
|
public static string GetIPFromCode(string code)
|
||||||
{
|
{
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
using PolyChat.Models;
|
|
||||||
using PolyChat.Util;
|
|
||||||
using System;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using Windows.UI.Popups;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
|
||||||
|
|
||||||
namespace PolyChat.Views
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
|
||||||
/// </summary>
|
|
||||||
public sealed partial class ConnectionFailedDialog : ContentDialog
|
|
||||||
{
|
|
||||||
public ConnectionFailedDialog(string message)
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
textError.Text = message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,20 @@
|
|||||||
<ContentDialog x:Class="PolyChat.Views.ConnectionFailedDialog"
|
<ContentDialog x:Class="PolyChat.Views.Dialog"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="using:PolyChat.Views"
|
xmlns:local="using:PolyChat.Views"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
x:Name="MessageDialog"
|
x:Name="MessageDialog"
|
||||||
Title="Connection Failed"
|
Title="Header"
|
||||||
PrimaryButtonText="Retry"
|
PrimaryButtonText="Primary"
|
||||||
SecondaryButtonText="Abort"
|
PrimaryButtonClick="OnPrimaryButtonClick"
|
||||||
|
SecondaryButtonText="Secondary"
|
||||||
|
SecondaryButtonClick="OnSecondaryButtonClick"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock Text="Message:" Foreground="{ThemeResource SystemColorDisabledTextColor}" Margin="0 0 0 8"/>
|
<TextBlock Text="Message:" Foreground="{ThemeResource SystemColorDisabledTextColor}" Margin="0 0 0 8"/>
|
||||||
<TextBlock x:Name="textError" Foreground="{ThemeResource SystemErrorTextColor}"/>
|
<TextBlock x:Name="textError" Foreground="{ThemeResource SystemErrorTextColor}" Visibility="Collapsed"/>
|
||||||
|
<TextBlock x:Name="textSuccess" Foreground="{ThemeResource SystemAccentColor}" Visibility="Collapsed"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ContentDialog>
|
</ContentDialog>
|
||||||
70
PolyChat/Views/Dialog.xaml.cs
Normal file
70
PolyChat/Views/Dialog.xaml.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using PolyChat.Models;
|
||||||
|
using PolyChat.Util;
|
||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.UI.Core;
|
||||||
|
using Windows.UI.Popups;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
||||||
|
|
||||||
|
namespace PolyChat.Views
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class Dialog : ContentDialog
|
||||||
|
{
|
||||||
|
public const string TYPE_ERROR = "error";
|
||||||
|
public const string TYPE_SUCCESS = "success";
|
||||||
|
private Action Primary;
|
||||||
|
private Action Secondary;
|
||||||
|
public Dialog(string type, string header, string message, DialogButton primary, DialogButton secondary)
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
Title = header;
|
||||||
|
setType(type, message);
|
||||||
|
PrimaryButtonText = primary.Text;
|
||||||
|
SecondaryButtonText = secondary.Text;
|
||||||
|
// TODO: use event handlers and asign actions here
|
||||||
|
Primary = primary.Action;
|
||||||
|
Secondary = secondary.Action;
|
||||||
|
RequestedTheme = MainPage.GetTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setType(string type, string message)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TYPE_ERROR:
|
||||||
|
textError.Text = message;
|
||||||
|
textError.Visibility = Visibility.Visible;
|
||||||
|
break;
|
||||||
|
case TYPE_SUCCESS:
|
||||||
|
textSuccess.Text = message;
|
||||||
|
textSuccess.Visibility = Visibility.Visible;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ShowDialogAsync()
|
||||||
|
{
|
||||||
|
await ShowAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||||
|
{
|
||||||
|
Primary();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||||
|
{
|
||||||
|
Secondary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ namespace PolyChat.Views
|
|||||||
if (initialValue == null || initialValue.Length == 0) IsSecondaryButtonEnabled = false;
|
if (initialValue == null || initialValue.Length == 0) IsSecondaryButtonEnabled = false;
|
||||||
else input.Text = initialValue;
|
else input.Text = initialValue;
|
||||||
validate();
|
validate();
|
||||||
|
RequestedTheme = MainPage.GetTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string getValue()
|
public string getValue()
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace PolyChat.Views
|
|||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
IsPrimaryButtonEnabled = false;
|
IsPrimaryButtonEnabled = false;
|
||||||
|
RequestedTheme = MainPage.GetTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string getValue()
|
public string getValue()
|
||||||
@@ -29,7 +30,7 @@ namespace PolyChat.Views
|
|||||||
|
|
||||||
private void OnKeyUp(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
|
private void OnKeyUp(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (!IP.ValidateIP(IP.GetIPfromCode(input.Text)))
|
if (!IP.ValidateIP(IP.GetIPFromCode(input.Text)))
|
||||||
{
|
{
|
||||||
textSuccess.Visibility = Visibility.Collapsed;
|
textSuccess.Visibility = Visibility.Collapsed;
|
||||||
textError.Visibility = Visibility.Visible;
|
textError.Visibility = Visibility.Visible;
|
||||||
|
|||||||
BIN
screenshots/polychat_dark.PNG
Normal file
BIN
screenshots/polychat_dark.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
screenshots/polychat_light.PNG
Normal file
BIN
screenshots/polychat_light.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Reference in New Issue
Block a user