private async void Page_OnLoaded(object sender, RoutedEventArgs e)
        {
            // load name of the user
            Title = "Chatting with " + (await SharedStuff.Database.Table <DatabaseHelper.Users>().Where(row => row.Username == Username)
                                        .FirstAsync()).Name;
            // load fist 100 messages
            var messages = await SharedStuff.Database.QueryAsync <DatabaseHelper.Messages>
                               (DatabaseHelper.LastRowsQuery(0, 100), Username);

            if (messages.Count < 100) // prevent additional load on db
            {
                _reachedEnd = true;
            }
            foreach (var message in messages)
            {
                if (message.Type == 0)
                {
                    MessagesList.Insert(0, new ChatMessagesNotify
                    {
                        MyMessage = message.MyMessage,
                        Message   = message.Payload,
                        FullDate  = message.Date,
                        Type      = message.Type,
                        Sent      = 0,
                        Progress  = 101
                    });
                }
                else if (message.Type == 1)
                {
                    var fileInfo = await SharedStuff.Database.Table <DatabaseHelper.Files>()
                                   .FirstAsync(file => file.Token == message.Payload);

                    var downloadButtonIcon = PackIconKind.Download;
                    if (!string.IsNullOrEmpty(fileInfo.Location))
                    {
                        downloadButtonIcon = File.Exists(fileInfo.Location) ? PackIconKind.File : PackIconKind.DownloadOff;
                    }
                    MessagesList.Insert(0, new ChatMessagesNotify
                    {
                        MyMessage          = message.MyMessage,
                        Message            = fileInfo.Name,
                        FullDate           = message.Date,
                        Type               = message.Type,
                        Sent               = 0,
                        Token              = message.Payload,
                        DownloadButtonIcon = downloadButtonIcon,
                        Progress           = 101
                    });
                }
            }

            MainScrollViewer.ScrollToBottom(); // Go to the last of scroll view that is actually the first of it
            MainScrollViewer.UpdateLayout();
            _stopLoading = false;
        }
 /// <summary>
 /// Add message to UI
 /// </summary>
 /// <param name="message">The message to add</param>
 public void AddMessage(ChatMessagesNotify message)
 {
     _lastMessageIndex++; //TODO: Will this make some problems when the message is not sent?
     Application.Current.Dispatcher.Invoke(() => MessagesList.Add(message));
     if (!message.MyMessage)
     {
         _stopLoading = true;
         // scroll to bottom if needed
         MainScrollViewer.UpdateLayout();
         if (MainScrollViewer.ScrollableHeight - MainScrollViewer.VerticalOffset < 30)
         {
             MainScrollViewer.ScrollToBottom();
             MainScrollViewer.UpdateLayout();
         }
         _stopLoading = false;
     }
 }
        /// <summary>
        /// Use this method to get older messages when VerticalOffset reaches 0 (scrolled to top)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void MainScrollViewer_OnScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (!_stopLoading && !_reachedEnd && Math.Abs(e.VerticalOffset) < 1) // load more messages
            {
                _stopLoading = true;
                // get last height
                double lastHeight = MainScrollViewer.ScrollableHeight;
                var    messages   = await SharedStuff.Database.QueryAsync <DatabaseHelper.Messages>
                                        (DatabaseHelper.LastRowsQuery(_lastMessageIndex, 100), Username);

                _lastMessageIndex += 100;
                // check if we have reached the end
                if (messages.Count < 100)
                {
                    _reachedEnd = true;
                }
                if (messages.Count == 0)
                {
                    return;
                }
                // insert these messages at the end of the list view (that is first of the collation)
                foreach (var message in messages)
                {
                    /*MessagesList.Insert(0, new ChatMessagesNotify
                     * {
                     *  MyMessage = message.MyMessage,
                     *  Message = message.Payload,
                     *  FullDate = message.Date,
                     *  Type = message.Type
                     * });*/
                    if (message.Type == 0)
                    {
                        MessagesList.Insert(0, new ChatMessagesNotify
                        {
                            MyMessage = message.MyMessage,
                            Message   = message.Payload,
                            FullDate  = message.Date,
                            Type      = message.Type,
                            Sent      = 0,
                            Progress  = 101
                        });
                    }
                    else if (message.Type == 1)
                    {
                        var fileInfo = await SharedStuff.Database.Table <DatabaseHelper.Files>()
                                       .FirstAsync(file => file.Token == message.Payload);

                        var downloadButtonIcon = PackIconKind.Download;
                        if (!string.IsNullOrEmpty(fileInfo.Location))
                        {
                            downloadButtonIcon = File.Exists(fileInfo.Location) ? PackIconKind.File : PackIconKind.DownloadOff;
                        }
                        MessagesList.Insert(0, new ChatMessagesNotify
                        {
                            MyMessage          = message.MyMessage,
                            Message            = fileInfo.Name,
                            FullDate           = message.Date,
                            Type               = message.Type,
                            Sent               = 0,
                            Token              = message.Payload,
                            DownloadButtonIcon = downloadButtonIcon,
                            Progress           = 101
                        });
                    }
                }
                MainScrollViewer.UpdateLayout();
                MainScrollViewer.ScrollToVerticalOffset(MainScrollViewer.ScrollableHeight - lastHeight); // tricky part; calculate the delta of height adding and go to that position from top
                MainScrollViewer.UpdateLayout();
                _stopLoading = false;
            }
        }
        private async void MessageTextBox_OnKeyDown(object sender, KeyEventArgs e)
        {
            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                if (Keyboard.IsKeyDown(Key.Enter))
                {
                    string message = MessageTextBox.Text.Trim().TrimEnd(Environment.NewLine.ToCharArray());
                    // do not send the message if it's empty
                    if (string.IsNullOrWhiteSpace(message))
                    {
                        return;
                    }
                    if (SharedStuff.Websocket.IsAlive)
                    {
                        string id = Guid.NewGuid().ToString();
                        await Task.Run(() => SendMessage(message, id)); // send message over network

                        var msgUi = new ChatMessagesNotify
                        {
                            MyMessage = true,
                            Message   = message,
                            FullDate  = DateTime.Now,
                            Type      = 0,
                            Sent      = 1
                        };
                        AddMessage(msgUi);                          // add it to ui
                        SharedStuff.PendingMessages.Add(id, msgUi); // add message to pending messages
                    }
                    else
                    {
                        var msgUi = new ChatMessagesNotify
                        {
                            MyMessage = true,
                            Message   = message,
                            FullDate  = DateTime.Now,
                            Type      = 0,
                            Sent      = 2
                        };
                        AddMessage(msgUi);
                    }
                    // finalizing UI
                    MessageTextBox.Text = "";
                    MessageTextBox.Focus();
                    _stopLoading = true;
                    MainScrollViewer.ScrollToBottom();
                    MainScrollViewer.UpdateLayout();
                    _stopLoading        = false;
                    SendButtonIcon.Kind = PackIconKind.Attachment;
                    SendButton.ToolTip  = "Send File";
                }
            }
            if (string.IsNullOrWhiteSpace(MessageTextBox.Text)) // show attachment icon
            {
                SendButtonIcon.Kind = PackIconKind.Attachment;
                SendButton.ToolTip  = "Send File";
            }
            else
            {
                SendButtonIcon.Kind = PackIconKind.Send;
                SendButton.ToolTip  = "Send Message";
            }
        }
        private async void SendBtnClicked(object sender, RoutedEventArgs e)
        {
            string message = MessageTextBox.Text.Trim();

            // initialize file send
            if (string.IsNullOrWhiteSpace(message))
            {
                OpenFileDialog ofd = new OpenFileDialog {
                    Title = "Send File"
                };
                bool?result = ofd.ShowDialog();
                if (result.HasValue && result.Value)
                {
                    string key = (await SharedStuff.Database.Table <DatabaseHelper.Users>().Where(user => user.Username == Username)
                                  .FirstAsync()).Key;
                    // at first request a token
                    string id    = Guid.NewGuid().ToString();
                    var    msgUi = new ChatMessagesNotify
                    {
                        MyMessage = true,
                        Message   = Path.GetFileName(ofd.FileName),
                        FullDate  = DateTime.Now,
                        Type      = 1,
                        Sent      = 1,
                        FilePath  = ofd.FileName,
                        With      = Username
                    };
                    SharedStuff.PendingMessages.Add(id, msgUi);
                    // create json
                    string json = JsonConvert.SerializeObject(new JsonTypes.SendMessage
                    {
                        Type    = 2,
                        Id      = id,
                        Payload = new JsonTypes.SendMessagePayload
                        {
                            To      = Username,
                            Message = Path.GetFileName(ofd.FileName)
                        }
                    });
                    SharedStuff.Websocket.SendAsync(json, null);
                    AddMessage(msgUi);
                }
            }
            else
            {
                if (SharedStuff.Websocket.IsAlive)
                {
                    string id = Guid.NewGuid().ToString();
                    await Task.Run(() => SendMessage(message, id));

                    var msgUi = new ChatMessagesNotify
                    {
                        MyMessage = true,
                        Message   = message,
                        FullDate  = DateTime.Now,
                        Type      = 0,
                        Sent      = 1
                    };
                    AddMessage(msgUi);                          // add it to ui
                    SharedStuff.PendingMessages.Add(id, msgUi); // add message to pending messages
                }
                else
                {
                    var msgUi = new ChatMessagesNotify
                    {
                        MyMessage = true,
                        Message   = message,
                        FullDate  = DateTime.Now,
                        Type      = 0,
                        Sent      = 2
                    };
                    AddMessage(msgUi);
                }

                // finalizing UI
                MessageTextBox.Text = "";
                MessageTextBox.Focus();
                _stopLoading = true;
                MainScrollViewer.ScrollToBottom();
                MainScrollViewer.UpdateLayout();
                _stopLoading        = false;
                SendButtonIcon.Kind = PackIconKind.Attachment;
                SendButton.ToolTip  = "Send File";
            }
        }