293 lines
9.3 KiB
C#
293 lines
9.3 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Dynamic;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Text;
|
|
using BITKit;
|
|
using BITKit.StateMachine;
|
|
using BITKit.UX;
|
|
using Cysharp.Threading.Tasks;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Net.BITKit.Chat;
|
|
using Newtonsoft.Json;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Net.Project.B.PDA.App
|
|
{
|
|
[Serializable]
|
|
public struct Chat : IApp
|
|
{
|
|
public string PackageName => "com.bndroid.chat";
|
|
public string AppName => "聊天";
|
|
}
|
|
|
|
public class AppChat : PDAApp<Chat>
|
|
{
|
|
private readonly IChatService _chatService;
|
|
private readonly IServiceProvider _serviceProvider;
|
|
protected override string DocumentPath => "ui_app_chat";
|
|
|
|
[UXBindPath("chat-panel")] private VisualElement _chatPanel;
|
|
[UXBindPath("chat_list-container")] private VisualElement _chatListContainer;
|
|
[UXBindPath("chat-container")] private VisualElement _chatContainer;
|
|
[UXBindPath("message-field")] private TextField _messageField;
|
|
[UXBindPath("send-button")] private Button _sendButton;
|
|
[UXBindPath("chat-scroll")] private ScrollView _chatScroll;
|
|
|
|
[UXBindPath("chat_user-label")] private Label _chatUserLabel;
|
|
|
|
[UXBindPath("is_typing-label")] private Label _isTypingLabel;
|
|
|
|
private VisualTreeAsset _chatTemplate;
|
|
private VisualTreeAsset _chatListTemplate;
|
|
|
|
private readonly ValidHandle _userTyping = new();
|
|
|
|
private readonly Dictionary<string, VisualElement> _chatList = new();
|
|
|
|
private string _currentUserId = string.Empty;
|
|
|
|
public AppChat(IServiceProvider serviceProvider, IChatService chatService)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
_chatService = chatService;
|
|
}
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
_chatTemplate = _chatContainer.Q<TemplateContainer>().templateSource;
|
|
_chatListTemplate = _chatListContainer.Q<TemplateContainer>().templateSource;
|
|
|
|
_messageField.RegisterValueChangedCallback(x =>
|
|
_sendButton.SetActive(string.IsNullOrEmpty(x.newValue) is false));
|
|
|
|
_sendButton.clicked += SendMessage;
|
|
|
|
_messageField.value = string.Empty;
|
|
|
|
_messageField.BlinkingCursor();
|
|
|
|
_messageField.RegisterCallback<KeyDownEvent>(OnKeyDown);
|
|
|
|
_userTyping.AddListener(_isTypingLabel.SetActive);
|
|
_userTyping.Invoke();
|
|
|
|
_chatListContainer.Clear()
|
|
;
|
|
_chatContainer.Clear();
|
|
|
|
_chatService.OnMessageReceived += OnMessageReceived;
|
|
|
|
_chatPanel.SetActive(false);
|
|
}
|
|
|
|
private void OnMessageReceived(ChatMessage obj)
|
|
{
|
|
if (obj.FromUserId != Environment.UserName && obj.ToUserId != Environment.UserName) return;
|
|
|
|
_serviceProvider.GetRequiredService<IPDAService>().Badge(App.PackageName);
|
|
|
|
var chatList = GetOrCreateChatList(obj);
|
|
|
|
if (obj.FromUserId != _currentUserId && obj.ToUserId != _currentUserId)
|
|
{
|
|
chatList.AddToClassList("allow-badge");
|
|
return;
|
|
}
|
|
|
|
CreateMessage(obj);
|
|
}
|
|
|
|
public override async UniTask OnStateEntryAsync(IState old)
|
|
{
|
|
await base.OnStateEntryAsync(old);
|
|
|
|
_chatListContainer.Clear();
|
|
_chatList.Clear();
|
|
foreach (var chatMessage in await _chatService.GetChatList(Environment.UserName))
|
|
{
|
|
GetOrCreateChatList(chatMessage);
|
|
}
|
|
}
|
|
|
|
private VisualElement GetOrCreateChatList(ChatMessage chatMessage)
|
|
{
|
|
var userName = string.Equals(chatMessage.FromUserId, Environment.UserName)
|
|
? chatMessage.ToUserId
|
|
: chatMessage.FromUserId;
|
|
|
|
if (_chatList.TryGetValue(userName, out var container))
|
|
{
|
|
container.Get<Label>().text = $"{userName} at{chatMessage.Timestamp:HH:mm}";
|
|
container.Get<Label>(1).text = chatMessage.Content.Split("\n").First();
|
|
return container;
|
|
}
|
|
|
|
container = _chatList[userName] = _chatListContainer.Create(_chatListTemplate);
|
|
|
|
container.viewDataKey = userName;
|
|
|
|
container.Get<Label>().text = userName;
|
|
container.Get<Label>(1).text = chatMessage.Content;
|
|
container.Get<Label>(2).text = userName[0].ToString();
|
|
|
|
container.Get<Button>().clicked += () => Chat(userName);
|
|
|
|
_chatList[userName] = container;
|
|
|
|
return container;
|
|
}
|
|
|
|
private async void Chat(string userId)
|
|
{
|
|
_chatUserLabel.text = _currentUserId = userId;
|
|
|
|
foreach (var visualElement in _chatListContainer.Children())
|
|
{
|
|
if (visualElement.viewDataKey == userId)
|
|
{
|
|
visualElement.AddToClassList("selected");
|
|
visualElement.RemoveFromClassList("allow-badge");
|
|
}
|
|
else
|
|
{
|
|
visualElement.RemoveFromClassList("selected");
|
|
}
|
|
}
|
|
|
|
_chatContainer.Clear();
|
|
|
|
foreach (var chatMessage in await _chatService.GetMessages(Environment.UserName, userId))
|
|
{
|
|
CreateMessage(chatMessage);
|
|
}
|
|
|
|
_chatScroll.ScrollToBottom();
|
|
|
|
_userTyping.RemoveElement(this);
|
|
|
|
_chatPanel.SetActive(true);
|
|
}
|
|
|
|
private void CreateMessage(ChatMessage chatMessage)
|
|
{
|
|
var container = _chatContainer.Create(_chatTemplate);
|
|
|
|
container.Get<Label>().text = chatMessage.Content;
|
|
container.Get<Label>(1).text =$"{chatMessage.FromUserId} at{chatMessage.Timestamp:HH:mm}";
|
|
container.Get<Label>(2).text = chatMessage.ToUserId[0].ToString();
|
|
|
|
if (!string.Equals(chatMessage.FromUserId, Environment.UserName)) return;
|
|
container.Get<Label>(2).text = chatMessage.FromUserId[0].ToString();
|
|
container.AddToClassList("self");
|
|
}
|
|
|
|
private void OnKeyDown(KeyDownEvent keyDownEvent)
|
|
{
|
|
switch (keyDownEvent.keyCode)
|
|
{
|
|
case KeyCode.Return:
|
|
|
|
SendMessage();
|
|
|
|
keyDownEvent.StopPropagation();
|
|
keyDownEvent.PreventDefault();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private async void SendMessage()
|
|
{
|
|
try
|
|
{
|
|
var message = _messageField.value;
|
|
if (string.IsNullOrEmpty(message)) return;
|
|
|
|
_userTyping.AddElement(this);
|
|
|
|
_messageField.value = "";
|
|
|
|
var currentUserId = _currentUserId;
|
|
|
|
await _chatService.SendMessage(new ChatMessage
|
|
{
|
|
FromUserId = Environment.UserName,
|
|
ToUserId = currentUserId,
|
|
Content = message,
|
|
});
|
|
|
|
//_chatScroll.verticalScroller.value = _chatScroll.verticalScroller.highValue;
|
|
_chatScroll.ScrollToBottom();
|
|
//_chatScroll.ScrollToBottomAutomatic();
|
|
|
|
using var client = new HttpClient();
|
|
|
|
string url =
|
|
"http://server.bitfall.icu:18918/api/application/chat_message/ceb19752-185e-11f0-9541-0242ac120009";
|
|
|
|
dynamic data = new ExpandoObject() { };
|
|
|
|
data.message = message;
|
|
data.re_chat = false;
|
|
data.stream = false;
|
|
|
|
// 构造 JSON 数据
|
|
var json = JsonConvert.SerializeObject(data);
|
|
|
|
// 设置请求体
|
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
|
|
|
// 添加请求头
|
|
client.DefaultRequestHeaders.Clear();
|
|
client.DefaultRequestHeaders.Add("AUTHORIZATION", "application-012e89878ee3e8dcfc4bc59a0c5648ae");
|
|
client.DefaultRequestHeaders.Add("accept", "application/json");
|
|
|
|
// 发送请求
|
|
var response = await client.PostAsync(url, content);
|
|
|
|
string newMessage;
|
|
try
|
|
{
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
// 处理返回
|
|
json = await response.Content.ReadAsStringAsync();
|
|
|
|
var result = JsonConvert.DeserializeObject<dynamic>(json);
|
|
|
|
newMessage = result.data.content;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogException(e);
|
|
newMessage = e.Message;
|
|
}
|
|
|
|
await _chatService.SendMessage(new ChatMessage()
|
|
{
|
|
FromUserId = currentUserId,
|
|
ToUserId = Environment.UserName,
|
|
Content = newMessage
|
|
});
|
|
|
|
|
|
if (_currentUserId != currentUserId) return;
|
|
|
|
await UniTask.NextFrame();
|
|
|
|
_chatScroll.ScrollToBottom();
|
|
}
|
|
finally
|
|
{
|
|
_userTyping.RemoveElement(this);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|