diff --git a/PolyChat/Assets/polychat_logo.svg b/PolyChat/Assets/polychat_logo.svg
new file mode 100644
index 0000000..b4be3c6
--- /dev/null
+++ b/PolyChat/Assets/polychat_logo.svg
@@ -0,0 +1,82 @@
+
diff --git a/PolyChat/Controller.cs b/PolyChat/Controller.cs
new file mode 100644
index 0000000..64886bf
--- /dev/null
+++ b/PolyChat/Controller.cs
@@ -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 Connections = new Dictionary();
+
+ ///
+ /// Initializes Controller with UI access
+ ///
+ /// UWP UI Controller
+ 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));
+ }
+
+ }
+
+ ///
+ /// starts server for clients to connect to
+ ///
+ 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 entry in Connections)
+ {
+ SendMessage(entry.Key, type, content);
+ }
+ }
+
+ ///
+ /// Sends message to given ip
+ ///
+ ///
+ ///
+ ///
+ 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);
+ }
+
+ ///
+ /// if We recieve a message this method gets triggert
+ ///
+ /// ip from sender
+ /// String that is send
+ 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);
+ }
+
+ ///
+ /// Closes chat connection
+ ///
+ /// ip of user to be closed
+ ///
+ ///
+ 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);
+ }
+
+ ///
+ /// sends incoming message to ui
+ ///
+ /// ip of client that send the message
+ /// the json array that is ti be displayed in th gui
+ 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();
+ }
+
+ ///
+ /// returns your own ip that starts with 10. becuase that is our subnet
+ ///
+ ///
+ 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;
+ }
+
+ }
+}
diff --git a/PolyChat/MainPage.xaml b/PolyChat/MainPage.xaml
index 5484d94..550dcc3 100644
--- a/PolyChat/MainPage.xaml
+++ b/PolyChat/MainPage.xaml
@@ -13,10 +13,11 @@
-
+
+
@@ -37,7 +38,7 @@
-
+
@@ -53,14 +54,10 @@
-
+
-
-
-
-
-
-
+
+
@@ -97,13 +95,17 @@
-
+
+
+
+
-
-
-
-
-
+
+
+
+
diff --git a/PolyChat/MainPage.xaml.cs b/PolyChat/MainPage.xaml.cs
index 42f1ca2..9c45126 100644
--- a/PolyChat/MainPage.xaml.cs
+++ b/PolyChat/MainPage.xaml.cs
@@ -1,12 +1,17 @@
-using PolyChat.Models;
+using Newtonsoft.Json.Linq;
+using PolyChat.Models;
using PolyChat.Util;
using PolyChat.Views;
using System;
using System.Collections.ObjectModel;
+using System.Diagnostics;
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.Controls;
+using Windows.UI.Xaml.Media;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
@@ -17,63 +22,90 @@ namespace PolyChat
///
public sealed partial class MainPage : Page
{
- private NetworkingController networkingController;
+ private Controller Controller;
private ObservableCollection Partners;
private ChatPartner selectedPartner = null;
private string username;
+ private static ElementTheme Theme = ElementTheme.Light;
+
public MainPage()
{
this.InitializeComponent();
// init controller
- networkingController = new NetworkingController(this);
+ Controller = new Controller(this);
// ui variables
- ipAddress.Text = IP.GetCodeFromIP(networkingController.getIP().ToString());
+ ipAddress.Text = IP.GetCodeFromIP(Controller.getIP());
Partners = new ObservableCollection();
+ // theming
+ RequestedTheme = Theme;
+ // updated placeholder
updateNoChatsPlaceholder();
updateNoUsernamePlaceholder();
updateNoChatSelected();
updateSendButtonEnabled();
}
- public async void ShowConnectionError(string message)
+ public async void ShowConnectionError(string param, string heading, string message)
{
- ConnectionFailedDialog dialog = new ConnectionFailedDialog(message);
- var result = await dialog.ShowAsync();
- if (result == ContentDialogResult.Primary)
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
- //retry
- }
- // else abort -> del chat
+ Dialog dialog = new Dialog(
+ Dialog.TYPE_ERROR,
+ heading,
+ message,
+ new DialogButton(
+ "Retry",
+ () =>
+ {
+ Controller.Connect(param);
+ Partners.Add(new ChatPartner(
+ "Connecting...",
+ param
+ ));
+ updateNoChatsPlaceholder();
+ }
+ ),
+ new DialogButton(
+ "Ignore",
+ () => { /* do nothing */ }
+ )
+ );
+ SafelyOpenDialog(dialog);
+ });
}
// 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)
{
- selectedPartner.AddMessage(new Message(inputSend.Text,false));
- networkingController.sendMessage(selectedPartner.Code, inputSend.Text);
+ selectedPartner.AddMessage(new ChatMessage(username, "message", inputSend.Text, DateTime.Now, false));
+ Controller.SendMessage(selectedPartner.Code, "message", inputSend.Text);
// clear input
inputSend.Text = "";
}
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();
- var result = await dialog.ShowAsync();
+ var result = await SafelyOpenDialog(dialog);
if (result == ContentDialogResult.Primary)
{
- string ip = IP.GetIPfromCode(dialog.getValue());
- networkingController.connectNewClient(ip);
- Partners.Add(new ChatPartner(
+ string ip = IP.GetIPFromCode(dialog.getValue());
+ Controller.Connect(ip);
+ ChatPartner pa = Partners.FirstOrDefault(p => p.Code == ip);
+ if (pa == null)
+ Partners.Add(new ChatPartner(
"Connecting...",
ip
));
@@ -84,41 +116,133 @@ namespace PolyChat
public async void OnOpenEditUsernameDialog(object sender = null, RoutedEventArgs e = null)
{
EditUsernameDialog dialog = new EditUsernameDialog(username);
- var result = await dialog.ShowAsync();
+ var result = await SafelyOpenDialog(dialog);
if (result == ContentDialogResult.Primary)
{
username = dialog.getValue();
- if (username.Length == 0) textUsername.Text = "Unknown";
- else textUsername.Text = username;
+ textUsername.Text = username;
+ Controller.SendBroadcastMessage("username", username);
}
updateNoUsernamePlaceholder();
}
- public void OnIncomingMessage(Message message)
+ ///
+ /// Adds a new ChatPartner to the UI with default Name.
+ ///
+ /// IP Adress, gets shown as Util.IP > Code
+ public async void OnIncomingConnection(string ip)
{
- ChatPartner sendingPartner = Partners.First(p => p.Code == message.Ip);
- sendingPartner.AddMessage(new Message(
- message.Msg,
- true,
- message.Sender
- ));
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ Partners.Add(new ChatPartner(
+ "Connecting...",
+ ip
+ ));
+ updateNoChatsPlaceholder();
+ });
+ }
+ ///
+ /// Adds an message to the UI, based on .sender if known
+ ///
+ /// ChatMessage
+ 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)
{
+ Controller.CloseChat(selectedPartner.Code,delete: true);
Partners.Remove(selectedPartner);
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)
{
updateSendButtonEnabled();
- if (e.Key == Windows.System.VirtualKey.Enter)
+ if (buttonSend.IsEnabled && e.Key == Windows.System.VirtualKey.Enter)
{
OnSendMessage();
}
}
+ public static IAsyncOperation 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
private void updateNoChatsPlaceholder()
diff --git a/PolyChat/Models/ChatMessage.cs b/PolyChat/Models/ChatMessage.cs
index 28cf47c..1f6d272 100644
--- a/PolyChat/Models/ChatMessage.cs
+++ b/PolyChat/Models/ChatMessage.cs
@@ -1,29 +1,42 @@
using System;
+using System.Diagnostics;
+using System.Text.Json;
+using Windows.UI.Xaml;
namespace PolyChat.Models
{
public class ChatMessage
{
- public readonly string Sender;
- public readonly DateTime Timestamp = new DateTime(1970, 01, 01);
- public readonly string Content;
- public readonly string Ip;
- public readonly bool Foreign;
+ public string Origin;
+ public string Type;
+ public string Content;
+ public DateTime TimeStamp;
+ public HorizontalAlignment Align;
+ private bool Foreign;
- public ChatMessage(string Content = "", bool Foreign = true, string Sender= "Unknown", string Ip = "127.0.0.1")
+ ///
+ /// Create Message
+ ///
+ /// Origin IP
+ /// Message Type, usually "message"
+ /// Message Content, usually plain text
+ /// Parsed DateTime
+ public ChatMessage(string origin, string type, string content, DateTime timeStamp, bool foreign)
{
- this.Sender = Sender;
- this.Timestamp = DateTime.Now;
- this.Content = Content;
- this.Foreign = Foreign;
- this.Ip = Ip;
+ Origin = origin;
+ TimeStamp = timeStamp;
+ Type = type;
+ Content = content;
+ Align = foreign ? HorizontalAlignment.Right : HorizontalAlignment.Left;
+ Foreign = foreign;
+ Debug.WriteLine("Created Loaded Message: " + ToString());
}
override
public string ToString()
{
string prefix = Foreign ? "Other" : "Me";
- return $"{prefix}: {Content}({Sender})";
+ return $"{Type} from {prefix}: {Content}({Origin})";
}
}
}
\ No newline at end of file
diff --git a/PolyChat/Models/ChatPartner.cs b/PolyChat/Models/ChatPartner.cs
index 8b93455..abc5f00 100644
--- a/PolyChat/Models/ChatPartner.cs
+++ b/PolyChat/Models/ChatPartner.cs
@@ -1,5 +1,8 @@
using SocketIOSharp.Server.Client;
using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
namespace PolyChat.Models
{
@@ -7,20 +10,20 @@ namespace PolyChat.Models
{
public string Name;
public string Code;
- public ObservableCollection Messages;
+ public ObservableCollection Messages;
private SocketIOSocket socketIOSocket;
- public ChatPartner(string name, string code, ObservableCollection messages = null)
+ public ChatPartner(string name, string code, ObservableCollection messages = null)
{
Name = name;
Code = code;
- if (messages == null) Messages = new ObservableCollection();
+ if (messages == null) Messages = new ObservableCollection();
else Messages = messages;
}
public SocketIOSocket SocketIOSocket { get => socketIOSocket; set => socketIOSocket = value; }
- public void AddMessage(Message message)
+ public void AddMessage(ChatMessage message)
{
Messages.Add(message);
}
diff --git a/PolyChat/Models/Connection.cs b/PolyChat/Models/Connection.cs
new file mode 100644
index 0000000..5d45440
--- /dev/null
+++ b/PolyChat/Models/Connection.cs
@@ -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 DeleteConnection;
+
+ public Connection(string ip, ushort port, Action onMessage, Action 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) onMessage);
+ }
+
+ public Connection(SocketIOSocket socket, Action onMessage, Action onClose)
+ {
+ Socket = socket;
+ DeleteConnection = onClose;
+ Socket.On(SocketIOEvent.DISCONNECT, OnDisconnect);
+ Socket.On(SocketIOEvent.ERROR, (JToken[] Data) => OnError(Data));
+ Socket.On("message", (Action) 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;
+ }
+ }
+}
diff --git a/PolyChat/Models/DialogButton.cs b/PolyChat/Models/DialogButton.cs
new file mode 100644
index 0000000..959e5c2
--- /dev/null
+++ b/PolyChat/Models/DialogButton.cs
@@ -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;
+ }
+ }
+}
diff --git a/PolyChat/Models/FileManager.cs b/PolyChat/Models/FileManager.cs
new file mode 100644
index 0000000..d0ca688
--- /dev/null
+++ b/PolyChat/Models/FileManager.cs
@@ -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
+ //===============================================================================================================================================
+
+ ///
+ /// deletes chatlog of one speciffic user
+ ///
+ ///
+ 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;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// loads one chatlog probably when someone tries to connect
+ ///
+ ///
+ 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);
+ }
+ }
+ }
+
+ ///
+ /// sends chatlogs as json array to uiController with corrosponding ip
+ ///
+ /// in ui when chat is clicked connection gets established
+ ///
+ ///
+ 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);
+ }
+ }
+ }
+
+ ///
+ /// Saves incoming chat message to U:\PolyChat\Saves\ip.txt
+ ///
+ ///
+ ///
+ 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
+ //===============================================================================================================================================
+
+ ///
+ /// generates keypair [public, privte] (100% secure, trust me)
+ ///
+ ///
+ private String[] genKeys()
+ {
+ return new String[] {"12345678", "12345678" };
+ }
+
+
+ ///
+ /// does exactly what it says. XD
+ ///
+ /// encrypts given string and returns unreadable string
+ ///
+ ///
+ ///
+ 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);
+ }
+ }
+
+ ///
+ /// does exactly what it says. XD
+ ///
+ /// takes in unreadable string and returns infirmation
+ ///
+ ///
+ ///
+ 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);
+ }
+ }
+ }
+}
diff --git a/PolyChat/Models/MSG.cs b/PolyChat/Models/MSG.cs
deleted file mode 100644
index 637fc3b..0000000
--- a/PolyChat/Models/MSG.cs
+++ /dev/null
@@ -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
-{
- ///
- /// dumy class for json converter
- ///
- 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;
- }
- }
-}
diff --git a/PolyChat/Models/SendCode.cs b/PolyChat/Models/SendCode.cs
deleted file mode 100644
index 0995534..0000000
--- a/PolyChat/Models/SendCode.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace PolyChat.Models
-{
- enum SendCode
- {
- Message,
- Command,
- NameChange,
- Initial
- }
-}
\ No newline at end of file
diff --git a/PolyChat/Package.appxmanifest b/PolyChat/Package.appxmanifest
index 3d5e5b6..e3edf7e 100644
--- a/PolyChat/Package.appxmanifest
+++ b/PolyChat/Package.appxmanifest
@@ -13,8 +13,8 @@
+ Publisher="CN=PatrickMarcFelix"
+ Version="0.1.0.0" />
@@ -87,4 +87,4 @@
-
\ No newline at end of file
+
diff --git a/PolyChat/PolyChat.csproj b/PolyChat/PolyChat.csproj
index 3410aba..df5e9f4 100644
--- a/PolyChat/PolyChat.csproj
+++ b/PolyChat/PolyChat.csproj
@@ -17,7 +17,15 @@
512
{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
true
- false
+ False
+ False
+ False
+ True
+ Always
+ x86
+ 0
+ 6B0D12FC4E83C6F6997C60706A04799ED44B7E56
+ SHA256
true
@@ -119,20 +127,21 @@
App.xaml
+
+
+
MainPage.xaml
-
+
-
-
-
+
-
- ConnectionFailedDialog.xaml
+
+ Dialog.xaml
EditUsernameDialog.xaml
@@ -165,7 +174,7 @@
MSBuild:Compile
Designer
-
+
MSBuild:Compile
Designer
@@ -185,9 +194,15 @@
6.2.12
+
+ 0.9.13
+
2.0.3
+
+ 5.0.2
+
14.0
diff --git a/PolyChat/Util/IP.cs b/PolyChat/Util/IP.cs
index fcb6fd6..975dcd1 100644
--- a/PolyChat/Util/IP.cs
+++ b/PolyChat/Util/IP.cs
@@ -7,7 +7,7 @@ namespace PolyChat.Util
{
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;
}
diff --git a/PolyChat/Views/ConnectionFailedDialog.xaml.cs b/PolyChat/Views/ConnectionFailedDialog.xaml.cs
deleted file mode 100644
index 1c09a8f..0000000
--- a/PolyChat/Views/ConnectionFailedDialog.xaml.cs
+++ /dev/null
@@ -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
-{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class ConnectionFailedDialog : ContentDialog
- {
- public ConnectionFailedDialog(string message)
- {
- this.InitializeComponent();
- textError.Text = message;
- }
- }
-}
diff --git a/PolyChat/Views/ConnectionFailedDialog.xaml b/PolyChat/Views/Dialog.xaml
similarity index 59%
rename from PolyChat/Views/ConnectionFailedDialog.xaml
rename to PolyChat/Views/Dialog.xaml
index fa8916e..bc60eb8 100644
--- a/PolyChat/Views/ConnectionFailedDialog.xaml
+++ b/PolyChat/Views/Dialog.xaml
@@ -1,17 +1,20 @@
-
-
+
+
diff --git a/PolyChat/Views/Dialog.xaml.cs b/PolyChat/Views/Dialog.xaml.cs
new file mode 100644
index 0000000..f8b5bd6
--- /dev/null
+++ b/PolyChat/Views/Dialog.xaml.cs
@@ -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
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ 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();
+ }
+ }
+}
diff --git a/PolyChat/Views/EditUsernameDialog.xaml.cs b/PolyChat/Views/EditUsernameDialog.xaml.cs
index faec438..8e44c1e 100644
--- a/PolyChat/Views/EditUsernameDialog.xaml.cs
+++ b/PolyChat/Views/EditUsernameDialog.xaml.cs
@@ -22,6 +22,7 @@ namespace PolyChat.Views
if (initialValue == null || initialValue.Length == 0) IsSecondaryButtonEnabled = false;
else input.Text = initialValue;
validate();
+ RequestedTheme = MainPage.GetTheme();
}
public string getValue()
diff --git a/PolyChat/Views/NewChatDialog.xaml.cs b/PolyChat/Views/NewChatDialog.xaml.cs
index 600c62f..a77d96f 100644
--- a/PolyChat/Views/NewChatDialog.xaml.cs
+++ b/PolyChat/Views/NewChatDialog.xaml.cs
@@ -20,6 +20,7 @@ namespace PolyChat.Views
{
this.InitializeComponent();
IsPrimaryButtonEnabled = false;
+ RequestedTheme = MainPage.GetTheme();
}
public string getValue()
@@ -29,7 +30,7 @@ namespace PolyChat.Views
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;
textError.Visibility = Visibility.Visible;
diff --git a/screenshots/polychat_dark.PNG b/screenshots/polychat_dark.PNG
new file mode 100644
index 0000000..3251733
Binary files /dev/null and b/screenshots/polychat_dark.PNG differ
diff --git a/screenshots/polychat_light.PNG b/screenshots/polychat_light.PNG
new file mode 100644
index 0000000..86c4e88
Binary files /dev/null and b/screenshots/polychat_light.PNG differ