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<CommunityMedia,Task> send;
private readonly Action<string> 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<CommunityMedia,Task> send,Action<string> 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);");}
}
}
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<CommunityMedia,Task> send;
private readonly Action<string> 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<CommunityMedia,Task> send,Action<string> 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);");}
}
}