diff --git a/qtcnet-client/Forms/DirectMessageForm.Designer.cs b/qtcnet-client/Forms/DirectMessageForm.Designer.cs
new file mode 100644
index 0000000..9ec07eb
--- /dev/null
+++ b/qtcnet-client/Forms/DirectMessageForm.Designer.cs
@@ -0,0 +1,127 @@
+namespace qtcnet_client.Forms
+{
+ partial class DirectMessageForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ flpMessages = new FlowLayoutPanel();
+ btnSend = new Button();
+ rtxtChatbox = new RichTextBox();
+ pbProfileImage = new PictureBox();
+ lblUsername = new Label();
+ ((System.ComponentModel.ISupportInitialize)pbProfileImage).BeginInit();
+ SuspendLayout();
+ //
+ // flpMessages
+ //
+ flpMessages.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
+ flpMessages.AutoScroll = true;
+ flpMessages.BackColor = Color.White;
+ flpMessages.FlowDirection = FlowDirection.TopDown;
+ flpMessages.Location = new Point(12, 68);
+ flpMessages.Name = "flpMessages";
+ flpMessages.Size = new Size(589, 243);
+ flpMessages.TabIndex = 10;
+ flpMessages.WrapContents = false;
+ //
+ // btnSend
+ //
+ btnSend.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+ btnSend.BackgroundImage = Properties.Resources.SendIcon;
+ btnSend.BackgroundImageLayout = ImageLayout.Zoom;
+ btnSend.FlatAppearance.BorderSize = 0;
+ btnSend.FlatStyle = FlatStyle.Flat;
+ btnSend.Location = new Point(526, 328);
+ btnSend.Name = "btnSend";
+ btnSend.Size = new Size(75, 44);
+ btnSend.TabIndex = 9;
+ btnSend.UseVisualStyleBackColor = true;
+ btnSend.Click += btnSend_Click;
+ //
+ // rtxtChatbox
+ //
+ rtxtChatbox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
+ rtxtChatbox.Location = new Point(12, 317);
+ rtxtChatbox.Name = "rtxtChatbox";
+ rtxtChatbox.Size = new Size(508, 66);
+ rtxtChatbox.TabIndex = 8;
+ rtxtChatbox.Text = "";
+ rtxtChatbox.KeyDown += rtxtChatbox_KeyDown;
+ //
+ // pbProfileImage
+ //
+ pbProfileImage.Image = Properties.Resources.DefaultPfp;
+ pbProfileImage.Location = new Point(12, 12);
+ pbProfileImage.Name = "pbProfileImage";
+ pbProfileImage.Size = new Size(52, 50);
+ pbProfileImage.SizeMode = PictureBoxSizeMode.Zoom;
+ pbProfileImage.TabIndex = 11;
+ pbProfileImage.TabStop = false;
+ //
+ // lblUsername
+ //
+ lblUsername.AutoSize = true;
+ lblUsername.Font = new Font("Segoe UI", 20F, FontStyle.Bold | FontStyle.Italic);
+ lblUsername.ForeColor = Color.White;
+ lblUsername.Location = new Point(64, 17);
+ lblUsername.Name = "lblUsername";
+ lblUsername.Size = new Size(145, 37);
+ lblUsername.TabIndex = 12;
+ lblUsername.Text = "Username";
+ //
+ // DirectMessageForm
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ BackColor = Color.DodgerBlue;
+ ClientSize = new Size(612, 395);
+ Controls.Add(lblUsername);
+ Controls.Add(pbProfileImage);
+ Controls.Add(flpMessages);
+ Controls.Add(btnSend);
+ Controls.Add(rtxtChatbox);
+ FormBorderStyle = FormBorderStyle.FixedSingle;
+ MaximizeBox = false;
+ Name = "DirectMessageForm";
+ StartPosition = FormStartPosition.CenterScreen;
+ Text = "Direct Message";
+ FormClosed += DirectMessageForm_FormClosed;
+ Load += DirectMessageForm_Load;
+ ((System.ComponentModel.ISupportInitialize)pbProfileImage).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private FlowLayoutPanel flpMessages;
+ private Button btnSend;
+ private RichTextBox rtxtChatbox;
+ private PictureBox pbProfileImage;
+ private Label lblUsername;
+ }
+}
\ No newline at end of file
diff --git a/qtcnet-client/Forms/DirectMessageForm.cs b/qtcnet-client/Forms/DirectMessageForm.cs
new file mode 100644
index 0000000..c837930
--- /dev/null
+++ b/qtcnet-client/Forms/DirectMessageForm.cs
@@ -0,0 +1,130 @@
+using qtcnet_client.Controls;
+using qtcnet_client.Factories;
+using qtcnet_client.Properties;
+using QtCNETAPI.Dtos.User;
+using QtCNETAPI.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+namespace qtcnet_client.Forms
+{
+ public partial class DirectMessageForm : Form
+ {
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public string UserId { get; set; } = string.Empty;
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public string Username { get; set; } = "Username";
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public Image ProfileImage { get; set; } = Resources.DefaultPfp;
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Dictionary UserProfileImages { get; set; } = [];
+ public string SentMessage { get; private set; } = string.Empty;
+
+ public event EventHandler? OnSend;
+ public event EventHandler? OnClose;
+
+ private readonly ImageFactory _imgFactory;
+ public DirectMessageForm(ImageFactory imageFactory)
+ {
+ _imgFactory = imageFactory;
+ InitializeComponent();
+ }
+
+ private void DirectMessageForm_Load(object sender, EventArgs e)
+ {
+ lblUsername.Text = Username;
+ pbProfileImage.Image = ProfileImage;
+ }
+
+ private void btnSend_Click(object sender, EventArgs e)
+ {
+ if (ValidateChatBox())
+ {
+ SentMessage = rtxtChatbox.Text;
+ OnSend?.Invoke(this, EventArgs.Empty);
+ rtxtChatbox.Clear();
+ }
+ }
+
+ private void rtxtChatbox_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
+ {
+ if (ValidateChatBox())
+ {
+ SentMessage = rtxtChatbox.Text;
+ OnSend?.Invoke(this, EventArgs.Empty);
+ rtxtChatbox.Clear();
+ }
+ }
+ }
+
+ private void DirectMessageForm_FormClosed(object sender, FormClosedEventArgs e) => OnClose?.Invoke(this, EventArgs.Empty);
+
+ public async Task LoadProfileImage(MessageControl ctrl, UserInformationDto user)
+ {
+ _ = Task.Run(async () =>
+ {
+ var img = await AddUserProfileImageToDictionary(user);
+
+ if (img == null || ctrl.IsDisposed)
+ return;
+
+ if (ctrl.InvokeRequired)
+ ctrl.Invoke(() =>
+ {
+ ctrl.ProfileImage = img;
+ ctrl.ReloadProfileImage();
+ });
+ else
+ {
+ ctrl.ProfileImage = img;
+ ctrl.ReloadProfileImage();
+ }
+ });
+ }
+
+ private async Task AddUserProfileImageToDictionary(UserInformationDto user)
+ {
+ if (UserProfileImages.TryGetValue(user.Id, out var image))
+ return image;
+ else
+ {
+ var img = _imgFactory.GetAndCreateProfileImage(user.Id, -1, user.ProfileCosmeticId);
+ UserProfileImages.Add(user.Id, img);
+ return img;
+ }
+ }
+
+ public void AddMessage(MessageControl messageCtrl)
+ {
+ messageCtrl.Width = flpMessages.ClientSize.Width - 10;
+ messageCtrl.Margin = new Padding(0, 0, 0, 6);
+
+ if (flpMessages.InvokeRequired)
+ {
+ Invoke(() =>
+ {
+ flpMessages.Controls.Add(messageCtrl);
+ flpMessages.ScrollControlIntoView(messageCtrl);
+ });
+ }
+ else
+ {
+ flpMessages.Controls.Add(messageCtrl);
+ flpMessages.ScrollControlIntoView(messageCtrl);
+ }
+ }
+
+ private bool ValidateChatBox()
+ {
+ return !string.IsNullOrWhiteSpace(rtxtChatbox.Text) || !string.IsNullOrEmpty(rtxtChatbox.Text);
+ }
+ }
+}
diff --git a/qtcnet-client/Forms/DirectMessageForm.resx b/qtcnet-client/Forms/DirectMessageForm.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/qtcnet-client/Forms/DirectMessageForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/qtcnet-client/Forms/MainForm.cs b/qtcnet-client/Forms/MainForm.cs
index 5aed5c1..e077b24 100644
--- a/qtcnet-client/Forms/MainForm.cs
+++ b/qtcnet-client/Forms/MainForm.cs
@@ -25,6 +25,7 @@ namespace qtcnet_client
private MainTabControl? MainTabControl;
private readonly List OpenChatRoomForms = [];
+ private readonly List OpenDirectMessagesForms = [];
private readonly List OpenProfileForms = [];
private readonly List UserContactsList = [];
@@ -340,6 +341,7 @@ namespace qtcnet_client
_profile.ProfileImage = _imgFactory.GetAndCreateProfileImage(_user.Data.Id, _user.Data.Status, _user.Data.ProfileCosmeticId);
_profile.OnClose += ProfileForm_OnClose;
+ _profile.OnMessageClicked += ProfileForm_OnMessageClicked;
OpenProfileForms.Add(_profile);
_profile.Show();
@@ -347,6 +349,25 @@ namespace qtcnet_client
}
}
+ private void ProfileForm_OnMessageClicked(object? sender, EventArgs e)
+ {
+ if(sender is ProfileForm _profileForm)
+ {
+ // create dm form
+ DirectMessageForm _dmForm = new(_imgFactory)
+ {
+ UserId = _profileForm.UserId,
+ Username = _profileForm.Username,
+ ProfileImage = _imgFactory.GetAndCreateProfileImage(_profileForm.UserId, -1), // TODO - probably rework forms to take in models instead of individual params
+ };
+ _dmForm.OnClose += DirectMessage_OnClose;
+ _dmForm.OnSend += DirectMessage_OnSend;
+
+ _dmForm.Show();
+ OpenDirectMessagesForms.Add(_dmForm);
+ }
+ }
+
private async void MainTabControl_OnUserItemDoubleClicked(object? sender, EventArgs e)
{
if (sender is MainTabControl _mtCtrl)
@@ -526,9 +547,84 @@ namespace qtcnet_client
}
}
- private void _gatewayService_OnDirectMessageReceived(object? sender, EventArgs e)
+ private async void _gatewayService_OnDirectMessageReceived(object? sender, EventArgs e)
{
- throw new NotImplementedException();
+ if(e is DirectMessageEventArgs _args)
+ {
+ // check for existing open form
+ var _existingForm = OpenDirectMessagesForms.FirstOrDefault(e => e.UserId == _args.User.Id);
+ if (_existingForm != null)
+ {
+ // just create a new message ctrl and add it
+ MessageControl _newMsg = new()
+ {
+ Message = _args.Message.Content,
+ Username = _args.User.Username,
+ };
+
+ _existingForm.AddMessage(_newMsg);
+ await _existingForm.LoadProfileImage(_newMsg, _args.User);
+ _audioService.PlaySoundEffect("sndMessage");
+ }
+ else
+ {
+ // create a new form
+ DirectMessageForm _dmForm = new(_imgFactory)
+ {
+ UserId = _args.User.Id,
+ Username = _args.User.Username,
+ ProfileImage = _imgFactory.GetAndCreateProfileImage(_args.User.Id, -1, _args.User.ProfileCosmeticId),
+ };
+ _dmForm.OnSend += DirectMessage_OnSend;
+ _dmForm.OnClose += DirectMessage_OnClose;
+
+ // add the new message to it
+ MessageControl _msg = new()
+ {
+ Username = _args.User.Username,
+ Message = _args.Message.Content,
+ };
+
+ _dmForm.AddMessage(_msg);
+ await _dmForm.LoadProfileImage(_msg, _args.User);
+
+ Task.Run(_dmForm.ShowDialog); // workaround async issues (i suck at coding and dont wanna rework the entire ui again)
+ OpenDirectMessagesForms.Add(_dmForm);
+ }
+ }
+ }
+
+ private void DirectMessage_OnClose(object? sender, EventArgs e)
+ {
+ if (sender is DirectMessageForm _dmForm)
+ {
+ OpenDirectMessagesForms.Remove(_dmForm);
+ _dmForm.Dispose();
+ }
+ }
+
+ private async void DirectMessage_OnSend(object? sender, EventArgs e)
+ {
+ if(sender is DirectMessageForm _dmForm)
+ {
+ // send message to user
+ var _userInfo = await _apiService.GetUserInformationAsync(_dmForm.UserId);
+ if(_userInfo.Success && _userInfo.Data != null)
+ {
+ await _gatewayService.SendDirectMessageAsync(_userInfo.Data, new QtCNETAPI.Models.Message { Content = _dmForm.SentMessage });
+
+ // add own message to form message list
+ MessageControl _selfMsg = new()
+ {
+ Username = _apiService.CurrentUser!.Username,
+ Message = _dmForm.SentMessage,
+ };
+
+ _dmForm.AddMessage(_selfMsg);
+ await _dmForm.LoadProfileImage(_selfMsg, new UserInformationDto { Id = _apiService.CurrentUser!.Id, ProfileCosmeticId = _apiService.CurrentUser.ActiveProfileCosmetic });
+ _audioService.PlaySoundEffect("sndSendClick");
+ }
+ }
}
private async Task PingAPI()
@@ -592,7 +688,7 @@ namespace qtcnet_client
_gatewayService.OnServerReconnecting += _gatewayService_OnServerReconnecting;
_gatewayService.OnServerReconnected += _gatewayService_OnServerReconnected;
_gatewayService.OnServerDisconnect += _gatewayService_OnServerDisconnect;
- //_gatewayService.OnDirectMessageReceived += _gatewayService_OnDirectMessageReceived;
+ _gatewayService.OnDirectMessageReceived += _gatewayService_OnDirectMessageReceived;
_gatewayService.OnRoomMessageReceived += _gatewayService_OnRoomMessageReceived;
_gatewayService.OnRoomUserListReceived += _gatewayService_OnRoomUserListReceived;
_gatewayService.OnRefreshUserListsReceived += _gatewayService_OnRefreshUserListReceived;
diff --git a/qtcnet-client/Forms/ProfileForm.cs b/qtcnet-client/Forms/ProfileForm.cs
index 7c88d67..6fcd1c3 100644
--- a/qtcnet-client/Forms/ProfileForm.cs
+++ b/qtcnet-client/Forms/ProfileForm.cs
@@ -33,6 +33,7 @@ namespace qtcnet_client.Forms
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Image ProfileImage { get; set; } = Resources.DefaultPfp;
+ public event EventHandler? OnMessageClicked;
public event EventHandler? OnClose;
private IApiService _apiService;
@@ -177,7 +178,8 @@ namespace qtcnet_client.Forms
private void BtnAction1_MessageClick(object? sender, EventArgs e)
{
- throw new NotImplementedException();
+ Close();
+ OnMessageClicked?.Invoke(this, EventArgs.Empty);
}
private async void BtnAction2_RemoveContactClick(object? sender, EventArgs e)