using System.Text.Json; using JiDangJia.Contracts; using JiDangJia.Services; namespace JiDangJia.Views; internal sealed class ChatVoiceInput : ContentView { private readonly CommunityWebView web=new(){HeightRequest=48}; private readonly ContentPage page; private readonly Func send; private readonly Action status; private readonly string account=AuthClient.Current.AccountId; private MemoryStream data=new(); private string upload=Guid.NewGuid().ToString("N"); private bool active,busy,receiving; public ChatVoiceInput(ContentPage page,Func send,Action status) { this.page=page;this.send=send;this.status=status;Content=web;web.MessageReceived+=Message;_=Prepare(); } private async Task Prepare(){try{using var stream=await FileSystem.OpenAppPackageFileAsync("community/voice-input.html");using var reader=new StreamReader(stream);web.Html=await reader.ReadToEndAsync();}catch(Exception ex){status(ex.Message);}} public void Start(){active=!AuthClient.Current.Locked&&account==AuthClient.Current.AccountId;if(active&&!busy&&web.Handler is not null)_=web.Run("window.setSending(false);");} public void Stop(){active=false;web.Stop();receiving=false;if(!busy)data.SetLength(0);} private async void Message(string value) { if(!active||value=="ready")return; try { using var document=JsonDocument.Parse(value);var message=document.RootElement; switch(message.GetProperty("type").GetString()) { case "permission": if(busy||!await CommunitySafetyUi.Write(page))return; await CommunityCapturePage.PermissionsFor("AUDIO"); if(active&&account==AuthClient.Current.AccountId)await web.Run("window.permissionReady();");break; case "status":status(message.GetProperty("message").GetString()??"");break; case "start":data.SetLength(0);upload=Guid.NewGuid().ToString("N");receiving=true;break; case "chunk": if(!receiving||busy)return;var bytes=Convert.FromBase64String(message.GetProperty("data").GetString()!);if(data.Length+bytes.Length>5*1024*1024)throw new ArgumentException("语音过大,请重新录制");data.Write(bytes);break; case "complete": if(!receiving||busy)return;receiving=false;busy=true; try{status("正在发送语音…");var media=await AuthClient.Current.UploadMedia(data.ToArray(),"AUDIO",upload,forChat:true);if(active&&account==AuthClient.Current.AccountId)await send(media);status("");} finally{busy=false;data.SetLength(0);if(active)await web.Run("window.setSending(false);");}break; } } catch(Exception ex){receiving=false;busy=false;status(ex.Message);if(active)await web.Run("window.setSending(false);");} } }