Net.Like.Xue.Tokyo/Packages-Local/Net.BITKit.Chat/IChatService.cs

144 lines
4.7 KiB
C#

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<IReadOnlyList<ChatMessage>> GetMessages(string userId);
UniTask<IReadOnlyList<ChatMessage>> GetMessages(string userId1, string userId2);
UniTask<IReadOnlyList<ChatMessage>> GetChatList(string userId);
public event Action<ChatMessage> OnMessageReceived;
}
public interface IChatVoiceService
{
}
public class ChatService : IChatService
{
private readonly IDictionary<int,ChatMessage> _messages;
public ChatService(IDictionary<int, ChatMessage> 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<IReadOnlyList<ChatMessage>> GetMessages(string userId)
{
var list = new List<ChatMessage>();
list.AddRange(_messages.Values.Where(x=>x.FromUserId==userId));
list.Sort((a, b) => a.Timestamp.CompareTo(b.Timestamp));
return UniTask.FromResult<IReadOnlyList<ChatMessage>>(list);
}
public UniTask<IReadOnlyList<ChatMessage>> GetMessages(string userId1, string userId2)
{
var list = new List<ChatMessage>();
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<IReadOnlyList<ChatMessage>>(list);
}
public UniTask<IReadOnlyList<ChatMessage>> GetChatList(string userId)
{
var result = new List<ChatMessage>();
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<IReadOnlyList<ChatMessage>>(result);
}
public event Action<ChatMessage> OnMessageReceived;
}
public static class ChatMockDataGenerator
{
private static int _count;
public static List<ChatMessage> GenerateMockMessages(int countPerUser = 10)
{
var systemUserId = Environment.UserName;
var otherUsers = new[] { "bob", "alice", "lucy", "john", "eva" };
var messages = new List<ChatMessage>();
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();
}
}
}