using System; using System.Collections; using System.Collections.Generic; using System.Net.Http; using BITKit; using BITKit.UX; using Cysharp.Threading.Tasks; using Microsoft.Extensions.Logging; using Net.BITKit; using Net.BITKit.Chat; using Net.Project.B.UX; using Newtonsoft.Json; using Project.B.Player; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UIElements; using Object = System.Object; namespace Net.Project.B.Chat { public class UXChat : UIToolkitSubPanel,IDisposable, IUXChat where TPanel : IUXPanel { private readonly IChatService _chatService; private readonly IUXKeyMap _uxKeyMap; private readonly ILogger> _logger; [UXBindPath("chat-field-container")] private VisualElement _chatFieldContainer; [UXBindPath("chat-container")] private VisualElement _chatContainer; [UXBindPath("chat-field")] private TextField _chatField; [UXBindPath("chat-scroll")] private ScrollView _chatScroll; [UXBindPath("voice-button")] private Button _voiceButton; private readonly ValidHandle _isEnabled = new(); private string _currentDevice; private AudioClip _recordClip; private UniTaskCompletionSource _waitVoice; public UXChat(IServiceProvider serviceProvider, IChatService chatService, IUXKeyMap uxKeyMap, ILogger> logger) : base(serviceProvider) { _chatService = chatService; _uxKeyMap = uxKeyMap; _logger = logger; _chatService.OnMessageReceived += OnMessageReceived; } private async void OnVoice() { _chatField.SetEnabled(false); _currentDevice = Microphone.devices[0]; _logger.LogInformation("开始录音"); _recordClip = Microphone.Start(_currentDevice, false, 10, 16000); try { await _waitVoice.Task; _logger.LogInformation("录音完成"); } catch (OperationCanceledException) { _logger.LogInformation("录音取消"); return; } finally { Microphone.End(_currentDevice); _waitVoice = null; } var newGo = new GameObject(); var audioSource = newGo.AddComponent(); audioSource.clip = _recordClip; audioSource.Play(); var wav = AudioClipUtils.AudioClipToWavBytes(_recordClip); await UniTask.Delay(TimeSpan.FromSeconds(_recordClip.length)); if (audioSource) { UnityEngine.Object.Destroy(newGo); } using var httpClient = new HttpClient(); var responseMessage = await httpClient.PostAsync(@"http://localhost:5062/api/vosk/gettext?modelName=vosk-model-en-us-0.42-gigaspeech", new ByteArrayContent(wav)); var message = await responseMessage.Content.ReadAsStringAsync(); _chatField.SetEnabled(true); var data = JsonConvert.DeserializeObject(message); Debug.Log(message); _chatField.value = data.text; } protected override void OnInitiated() { base.OnInitiated(); _chatContainer.Clear(); if (Panel is UIToolKitPanel panel) { panel.InputActionGroup.RegisterCallback(_uxKeyMap.ChatKey, OnChat); panel.OnExit+=()=> { _isEnabled.SetElements(this,false); }; } _isEnabled.AddListener(enabled => { _chatFieldContainer.SetActive(enabled); _voiceButton.SetActive(enabled); if (enabled) { BITInputSystem.AllowInput.AddDisableElements(this); BITAppForUnity.AllowCursor.AddElement(this); _chatField.SetActive(true); _chatField.focusable = true; _chatField.schedule.Execute(_chatField.Focus).ExecuteLater(1); _chatScroll.ScrollToBottom(); _chatScroll.focusable = true; } else { _waitVoice?.TrySetCanceled(); BITAppForUnity.AllowCursor.RemoveElement(this); BITInputSystem.AllowInput.RemoveDisableElements(this); _chatField.focusable = false; _chatField.schedule.Execute(()=> { _chatScroll.ScrollToBottom(); _chatField.SetActive(false); _chatField.SetValueWithoutNotify(string.Empty); _chatField.Blur(); }).ExecuteLater(1); _chatScroll.focusable = false; } _chatScroll.Blur(); }); _isEnabled.Invoke(); _chatField.RegisterCallback(OnKeyDown); _chatField.BlinkingCursor(); _voiceButton.clicked += ToggleVoice; } private void ToggleVoice() { if (_waitVoice is not null) { _waitVoice.TrySetResult(); } else { _waitVoice = new(); OnVoice(); } } private void OnKeyDown(KeyDownEvent keyDownEvent) { switch (keyDownEvent.keyCode) { case KeyCode.Return: if (string.IsNullOrEmpty(_chatField.value) is false) { _chatService.SendMessage(new ChatMessage() { FromUserId = Environment.UserName, ToUserId = "World", Content = _chatField.value }); _chatField.value = string.Empty; keyDownEvent.StopPropagation(); keyDownEvent.PreventDefault(); } break; } } private void OnChat(InputAction.CallbackContext obj) { if (obj.JustPressed() is false)return; _isEnabled.SetElements(this,!_isEnabled.Allow); } private void OnMessageReceived(ChatMessage obj) { var label = _chatContainer.Create