using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using BITKit; using Cysharp.Threading.Tasks; namespace Net.BITKit.Chat { public interface IChatService { UniTask SendMessage(ChatMessage message); UniTask> GetMessages(string userId); UniTask> GetMessages(string userId1, string userId2); UniTask> GetChatList(string userId); public event Action OnMessageReceived; } public interface IChatVoiceService { } public class ChatService : IChatService { private readonly IDictionary _messages; public ChatService(IDictionary messages) { _messages = messages; if (_messages.Count is 0) { foreach (var chatMessage in ChatMockDataGenerator.GenerateMockMessages()) { _messages.Add(chatMessage.Id,chatMessage); } } } public UniTask SendMessage(ChatMessage message) { if (_messages.ContainsKey(message.Id)) { message.Id = Guid.NewGuid().GetHashCode(); } _messages.Add(message.Id,message); OnMessageReceived?.Invoke(message); return UniTask.CompletedTask; } public UniTask> GetMessages(string userId) { var list = new List(); list.AddRange(_messages.Values.Where(x=>x.FromUserId==userId)); list.Sort((a, b) => a.Timestamp.CompareTo(b.Timestamp)); return UniTask.FromResult>(list); } public UniTask> GetMessages(string userId1, string userId2) { var list = new List(); list.AddRange(_messages.Values.Where(x=>(x.FromUserId==userId1&&x.ToUserId==userId2) || (x.FromUserId==userId2&&x.ToUserId==userId1))); list.Sort((a, b) => a.Timestamp.CompareTo(b.Timestamp)); return UniTask.FromResult>(list); } public UniTask> GetChatList(string userId) { var result = new List(); foreach (var chatMessage in _messages.Values) { if (chatMessage.FromUserId == userId || chatMessage.ToUserId == userId) { result.Add(chatMessage); } } #if NET5_0_OR_GREATER result = result.OrderByDescending(m => m.Timestamp).DistinctBy(x=>new { x.FromUserId, x.ToUserId }).ToList(); #else result = result .OrderByDescending(m => m.Timestamp) .GroupBy(x => new { x.FromUserId, x.ToUserId }) // 按这两个字段分组 .Select(g => g.First()) // 每组取最新的一条 .ToList(); #endif return UniTask.FromResult>(result); } public event Action OnMessageReceived; } public static class ChatMockDataGenerator { private static int _count; public static List GenerateMockMessages(int countPerUser = 10) { var systemUserId = Environment.UserName; var otherUsers = new[] { "bob", "alice", "lucy", "john", "eva" }; var messages = new List(); var rnd = new Random(); foreach (var otherUser in otherUsers) { for (int i = 0; i < countPerUser; i++) { // 随机决定谁说话 bool fromSystem = rnd.NextDouble() < 0.5; messages.Add(new ChatMessage { Id = _count++, FromUserId = fromSystem ? systemUserId : otherUser, ToUserId = fromSystem ? otherUser : systemUserId, Content = fromSystem ? $"Hi {otherUser}, message {i}" : $"Hey {systemUserId}, reply {i}", Timestamp = DateTime.Now.AddMinutes(-rnd.Next(0, 60 * 24 * 3)) // 过去3天内 }); } } return messages.OrderBy(m => m.Timestamp).ToList(); } } }