413 lines
14 KiB
C#
413 lines
14 KiB
C#
using FCOMMON;
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
|
|
namespace Project.Dialog
|
|
{
|
|
/// <summary>
|
|
/// User info for recipient selection
|
|
/// </summary>
|
|
public class ChatUserInfo
|
|
{
|
|
public string EmployeeId { get; set; }
|
|
public string NickName { get; set; }
|
|
public string UserGroup { get; set; }
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{NickName} ({EmployeeId})";
|
|
}
|
|
}
|
|
|
|
public partial class fChat : fBase
|
|
{
|
|
private ChatClientService chatService;
|
|
private string targetEmployeeId;
|
|
private string targetNickName;
|
|
|
|
/// <summary>
|
|
/// Constructor for new chat or specific recipient
|
|
/// </summary>
|
|
public fChat(ChatClientService service, string targetEmployeeId = null, string targetNickName = null)
|
|
{
|
|
InitializeComponent();
|
|
this.chatService = service;
|
|
this.targetEmployeeId = targetEmployeeId;
|
|
this.targetNickName = targetNickName;
|
|
this.KeyDown += (s, e) => { if (e.KeyCode == Keys.Escape) this.Close(); };
|
|
}
|
|
|
|
private void fChat_Load(object sender, EventArgs e)
|
|
{
|
|
// Subscribe to message received event
|
|
if (chatService != null)
|
|
{
|
|
chatService.MessageReceived += OnMessageReceived;
|
|
}
|
|
|
|
// Load user list for recipient selection
|
|
LoadUserList();
|
|
|
|
// If target is specified, set it
|
|
if (!string.IsNullOrEmpty(targetEmployeeId))
|
|
{
|
|
SetRecipient(targetEmployeeId, targetNickName);
|
|
}
|
|
|
|
// Load recent messages (if any)
|
|
RefreshConnectionStatus();
|
|
|
|
// Request user list from server
|
|
if (chatService != null && chatService.IsConnected)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("[DEBUG] Requesting user list from server...");
|
|
chatService.RequestUserList();
|
|
}
|
|
else
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] Cannot request user list - Service: {chatService != null}, Connected: {chatService?.IsConnected}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load user list into combobox
|
|
/// </summary>
|
|
private void LoadUserList()
|
|
{
|
|
cboRecipient.Items.Clear();
|
|
|
|
// Add placeholder
|
|
cboRecipient.Items.Add(new ChatUserInfo
|
|
{
|
|
EmployeeId = "",
|
|
NickName = "Select recipient...",
|
|
UserGroup = ""
|
|
});
|
|
|
|
// In a real implementation, this would load from server
|
|
// For now, user will need to type employee ID manually
|
|
// The server's UserListResponse should populate this
|
|
|
|
cboRecipient.SelectedIndex = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set specific recipient
|
|
/// </summary>
|
|
private void SetRecipient(string employeeId, string nickName)
|
|
{
|
|
targetEmployeeId = employeeId;
|
|
targetNickName = nickName;
|
|
|
|
// Try to find in combobox
|
|
bool found = false;
|
|
for (int i = 0; i < cboRecipient.Items.Count; i++)
|
|
{
|
|
var user = cboRecipient.Items[i] as ChatUserInfo;
|
|
if (user != null && user.EmployeeId == employeeId)
|
|
{
|
|
cboRecipient.SelectedIndex = i;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If not found, add it
|
|
if (!found && !string.IsNullOrEmpty(employeeId))
|
|
{
|
|
var user = new ChatUserInfo
|
|
{
|
|
EmployeeId = employeeId,
|
|
NickName = nickName ?? employeeId,
|
|
UserGroup = ""
|
|
};
|
|
cboRecipient.Items.Add(user);
|
|
cboRecipient.SelectedItem = user;
|
|
}
|
|
|
|
// Update form title
|
|
this.Text = $"Chat - {nickName ?? employeeId}";
|
|
}
|
|
|
|
private void fChat_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
// Unsubscribe events
|
|
if (chatService != null)
|
|
{
|
|
chatService.MessageReceived -= OnMessageReceived;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Message received event handler
|
|
/// </summary>
|
|
private void OnMessageReceived(object sender, ChatMessage message)
|
|
{
|
|
if (InvokeRequired)
|
|
{
|
|
BeginInvoke(new Action(() => OnMessageReceived(sender, message)));
|
|
return;
|
|
}
|
|
|
|
// Get current recipient from combobox
|
|
var selectedUser = cboRecipient.SelectedItem as ChatUserInfo;
|
|
string currentTargetId = selectedUser?.EmployeeId ?? targetEmployeeId;
|
|
|
|
// Filter messages - only show messages between current user and target
|
|
string myEmployeeId = chatService.EmployeeId;
|
|
|
|
// Show message if:
|
|
// 1. It's from target to me
|
|
// 2. It's from me to target (echo from server)
|
|
// 3. It's a notice (broadcast)
|
|
bool shouldDisplay = false;
|
|
|
|
if (message.Type == MessageType.Notice)
|
|
{
|
|
shouldDisplay = true;
|
|
|
|
// If it's a join/leave notice, refresh user list
|
|
if (message.Content.Contains("has joined") || message.Content.Contains("has left"))
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("[DEBUG] User joined/left, refreshing user list...");
|
|
if (chatService != null && chatService.IsConnected)
|
|
{
|
|
chatService.RequestUserList();
|
|
}
|
|
}
|
|
}
|
|
else if (message.Type == MessageType.UserListResponse)
|
|
{
|
|
// Handle user list response
|
|
HandleUserListResponse(message);
|
|
return;
|
|
}
|
|
else if (!string.IsNullOrEmpty(currentTargetId))
|
|
{
|
|
// From target to me
|
|
if (message.EmployeeId == currentTargetId && message.TargetEmployeeId == myEmployeeId)
|
|
{
|
|
shouldDisplay = true;
|
|
}
|
|
// From me to target (echo)
|
|
else if (message.EmployeeId == myEmployeeId && message.TargetEmployeeId == currentTargetId)
|
|
{
|
|
shouldDisplay = true;
|
|
}
|
|
}
|
|
|
|
if (shouldDisplay)
|
|
{
|
|
AppendMessage(message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handle user list response from server
|
|
/// </summary>
|
|
private void HandleUserListResponse(ChatMessage message)
|
|
{
|
|
try
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] UserListResponse received: {message.Content}");
|
|
|
|
// Parse user list from Content (format: "employeeId1:nickName1:userGroup1,employeeId2:nickName2:userGroup2,...")
|
|
if (string.IsNullOrEmpty(message.Content))
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("[DEBUG] UserListResponse content is empty");
|
|
return;
|
|
}
|
|
|
|
cboRecipient.Items.Clear();
|
|
|
|
// Add placeholder
|
|
cboRecipient.Items.Add(new ChatUserInfo
|
|
{
|
|
EmployeeId = "",
|
|
NickName = "Select recipient...",
|
|
UserGroup = ""
|
|
});
|
|
|
|
string[] users = message.Content.Split(',');
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] Parsing {users.Length} users");
|
|
|
|
foreach (var userStr in users)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(userStr))
|
|
continue;
|
|
|
|
string[] parts = userStr.Split(':');
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] User parts: {string.Join(", ", parts)}");
|
|
|
|
if (parts.Length >= 2)
|
|
{
|
|
string empId = parts[0].Trim();
|
|
string nick = parts[1].Trim();
|
|
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] Processing user: {empId} - {nick}, My ID: {chatService.EmployeeId}");
|
|
|
|
// Don't add myself
|
|
if (empId != chatService.EmployeeId)
|
|
{
|
|
var user = new ChatUserInfo
|
|
{
|
|
EmployeeId = empId,
|
|
NickName = nick,
|
|
UserGroup = parts.Length > 2 ? parts[2].Trim() : ""
|
|
};
|
|
cboRecipient.Items.Add(user);
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] Added user: {user}");
|
|
}
|
|
else
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] Skipped myself: {empId}");
|
|
}
|
|
}
|
|
}
|
|
|
|
System.Diagnostics.Debug.WriteLine($"[DEBUG] Total items in combo: {cboRecipient.Items.Count}");
|
|
|
|
// Restore previous selection if exists
|
|
if (!string.IsNullOrEmpty(targetEmployeeId))
|
|
{
|
|
SetRecipient(targetEmployeeId, targetNickName);
|
|
}
|
|
else
|
|
{
|
|
cboRecipient.SelectedIndex = 0;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[ERROR] HandleUserListResponse: {ex.Message}");
|
|
MessageBox.Show($"Error loading user list: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Append message to chat display
|
|
/// </summary>
|
|
private void AppendMessage(ChatMessage message)
|
|
{
|
|
string timeStr = message.Timestamp.ToString("HH:mm:ss");
|
|
string displayMsg = "";
|
|
|
|
switch (message.Type)
|
|
{
|
|
case MessageType.Chat:
|
|
displayMsg = $"[{timeStr}] {message.NickName}: {message.Content}";
|
|
break;
|
|
|
|
case MessageType.Notice:
|
|
displayMsg = $"[{timeStr}] [NOTICE] {message.Content}";
|
|
break;
|
|
|
|
case MessageType.Whisper:
|
|
displayMsg = $"[{timeStr}] [WHISPER from {message.NickName}] {message.Content}";
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
txtChatDisplay.AppendText(displayMsg + Environment.NewLine);
|
|
txtChatDisplay.ScrollToCaret();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Send button click
|
|
/// </summary>
|
|
private void btnSend_Click(object sender, EventArgs e)
|
|
{
|
|
SendMessage();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Input text key down (Enter to send)
|
|
/// </summary>
|
|
private void txtInput_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
e.SuppressKeyPress = true;
|
|
SendMessage();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Send chat message
|
|
/// </summary>
|
|
private void SendMessage()
|
|
{
|
|
string content = txtInput.Text.Trim();
|
|
if (string.IsNullOrEmpty(content))
|
|
return;
|
|
|
|
if (chatService == null || !chatService.IsConnected)
|
|
{
|
|
MessageBox.Show("Not connected to chat server.", "Chat", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
// Get target from combobox
|
|
var selectedUser = cboRecipient.SelectedItem as ChatUserInfo;
|
|
string currentTargetId = selectedUser?.EmployeeId ?? targetEmployeeId;
|
|
|
|
if (string.IsNullOrEmpty(currentTargetId))
|
|
{
|
|
MessageBox.Show("Please select a recipient.", "Chat", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
// Create message with target
|
|
var message = new ChatMessage
|
|
{
|
|
Type = MessageType.Chat,
|
|
Content = content,
|
|
TargetEmployeeId = currentTargetId
|
|
};
|
|
|
|
bool sent = chatService.SendMessage(message);
|
|
if (sent)
|
|
{
|
|
// Note: Server will echo the message back, so we don't display it here
|
|
// This prevents duplicate messages
|
|
|
|
// Clear input
|
|
txtInput.Text = "";
|
|
txtInput.Focus();
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Failed to send message.", "Chat", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Refresh connection status display
|
|
/// </summary>
|
|
private void RefreshConnectionStatus()
|
|
{
|
|
if (chatService != null && chatService.IsConnected)
|
|
{
|
|
lblStatus.Text = $"Connected - {chatService.NickName} ({chatService.UserGroup})";
|
|
lblStatus.ForeColor = Color.Green;
|
|
}
|
|
else
|
|
{
|
|
lblStatus.Text = "Disconnected";
|
|
lblStatus.ForeColor = Color.Red;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Timer to update status periodically
|
|
/// </summary>
|
|
private void timerStatus_Tick(object sender, EventArgs e)
|
|
{
|
|
RefreshConnectionStatus();
|
|
}
|
|
}
|
|
}
|