@page "/Chat" @page "/" @using Common.Dtos.Conversation @using Common.Dtos.Group @using Common.Enums @using HushianWebApp.Components @using HushianWebApp.Service @using HushianWebApp.Services @using Microsoft.AspNetCore.SignalR.Client @inject ChatService chatService @inject GroupService groupService @inject UserService userService @inject IJSRuntime JS @inject ToastService toastService @inject ILocalStorageService localStorageService; @inject HttpClient _Http; @inject NavigationManager nav گفتمان
@if (ChatCurrent != null) {

@SelectedChatUserName

@if (ChatCurrent.status == Common.Enums.ConversationStatus.InProgress) { } else if (ChatCurrent.status == Common.Enums.ConversationStatus.Finished && (CurrentUser.Role == "Company" || ChatCurrent.ExperID == CurrentUser.ExperID)) { }
} else if (isSelectedInbox1) {
نکته مهم

از انتخاب گفتگو مطمئن شوید، بعد از انتخاب شما مسئول بررسی می‌باشد

}
@if (ChatCurrent != null && ChatCurrent.Responses != null) {
@{ bool target = false; } @foreach (var msg in ChatCurrent?.Responses) { @if (!target && ((!msg.IsRead && msg.Type == Common.Enums.ConversationType.UE) || ChatCurrent.Responses.Last() == msg)) { target = true;
@if (!msg.IsRead && msg.Type == Common.Enums.ConversationType.UE) {
پیام جدید
}
}
@if (msg.FileContent != null && msg.FileContent.Length > 0 && !string.IsNullOrWhiteSpace(msg.FileType)) { @if (msg.FileType.StartsWith("image/")) { image } else if (msg.FileType.StartsWith("audio/")) {
@GetAudioDuration(msg.FileContent)
} @if (!string.IsNullOrWhiteSpace(msg.text)) {
@msg.text
} } else { @msg.text }
@if (msg.Type != Common.Enums.ConversationType.UE) { if (msg.IsRead) { } else { } }
} @{ target = false; }
} else {

هوشیان

}
@if (ChatCurrent != null && ChatCurrent.status != Common.Enums.ConversationStatus.Finished && ChatCurrent.Responses != null) {
}
@code { Common.Dtos.CurrentUserInfo CurrentUser { get; set; } List _Group = new List(); //------------------------------------- bool isSelectedInbox1 = false; List Inbox1Items { get; set; } = new(); bool isSelectedInbox2 = true; List Inbox2Items { get; set; } = new(); bool isSelectedInbox3 = false; List Inbox3Items { get; set; } = new(); ///////////// ChatItemDto? ChatCurrent { get; set; } = null; string MsgInput { get; set; } bool chatloading = false; string SelectedChatUserName = "مهدی ربیع نژاد"; private bool _shouldObserveVisibility = false; private ConfirmDialog dialog = default!; private Modal modal = default!; private HubConnection? hubConnection; } @functions { protected override async Task OnInitializedAsync() { CurrentUser = await userService.GetCurrentUserInfo(); _Group = await groupService.GetGroups(); Inbox1Items = await chatService.ChatAwaitingOurResponse(); Inbox2Items = await chatService.MyChatsIsInProgress(); Inbox3Items = await chatService.MyChatsIsFinished(); //-------------hub var token = await localStorageService.GetItem("C/key"); string AddressHub = _Http.BaseAddress.AbsoluteUri.Replace("api/", ""); hubConnection = new HubConnectionBuilder() .WithUrl($"{_Http.BaseAddress.AbsoluteUri.Replace("api/", "")}chatNotificationHub", options => { options.AccessTokenProvider = () => Task.FromResult(token); }) .WithAutomaticReconnect() .Build(); hubConnection.On("ReceiveNewChatItemFromUser", async (chatitem) => { if (ChatCurrent!=null && ChatCurrent.ID == chatitem.ChatItemID) { ChatCurrent.Responses.Add(chatitem); StateHasChanged(); await MarkAsRead(chatitem.ID); // Scroll to target if exists, otherwise scroll to bottom await JS.InvokeVoidAsync("scrollToTargetOrBottom"); } else if (Inbox2Items.Any(a => a.ID == chatitem.ChatItemID)) { Inbox2Items = await chatService.MyChatsIsInProgress(); StateHasChanged(); } }); hubConnection.On("CheckMarkAsRead", async (chatresponseid) => { if (ChatCurrent.Responses.Any(a => a.ID == chatresponseid && !a.IsRead && (a.Type == Common.Enums.ConversationType.EU || a.Type == Common.Enums.ConversationType.CU))) { ChatCurrent.Responses.First(a => a.ID == chatresponseid).IsRead = true; StateHasChanged(); } }); //NewChat hubConnection.On("NewChat", async (companyid) => { if (CurrentUser.CompanyID==companyid) { Inbox1Items = await chatService.ChatAwaitingOurResponse(); StateHasChanged(); } }); await hubConnection.StartAsync(); //---------end hub await base.OnInitializedAsync(); } protected override async Task OnAfterRenderAsync(bool firstRender) { if (_shouldObserveVisibility) { _shouldObserveVisibility = false; await JS.InvokeVoidAsync("observeVisibility", DotNetObjectReference.Create(this)); await JS.InvokeVoidAsync("scrollToTarget"); } } async Task OnclickInbox(int ID) { switch (ID) { case 1: isSelectedInbox1 = true; isSelectedInbox2 = false; isSelectedInbox3 = false; Inbox1Items = await chatService.ChatAwaitingOurResponse(); break; case 2: isSelectedInbox2 = true; isSelectedInbox1 = false; isSelectedInbox3 = false; Inbox2Items = await chatService.MyChatsIsInProgress(); break; case 3: isSelectedInbox3 = true; isSelectedInbox2 = false; isSelectedInbox1 = false; Inbox3Items = await chatService.MyChatsIsFinished(); break; } ChatCurrent = null; StateHasChanged(); } async Task OnClickSendMsg() { if (!string.IsNullOrEmpty(MsgInput) && ChatCurrent != null) { Common.Enums.ConversationType type = CurrentUser.Role == "Company" ? Common.Enums.ConversationType.CU : Common.Enums.ConversationType.EU; var geter= await chatService.ADDChatResponse(ChatCurrent.ID, MsgInput, type); if(geter!=null) {ChatCurrent?.Responses.Add(geter); ChatCurrent.LastText = MsgInput; await Task.Yield(); await JS.InvokeVoidAsync("scrollToBottom", "B1"); MsgInput = string.Empty;} } } async Task onClickSelectedChat(int InboxID, ChatItemDto chatItem) { chatloading = true; SelectedChatUserName = "در حال گفتگو با " + chatItem.UserFullName; ChatCurrent = chatItem; _shouldObserveVisibility = true; // فعال کن تا در OnAfterRenderAsync صدا زده بشه StateHasChanged(); // مجبور کن Blazor رندر کنه chatloading = false; } [JSInvokable] public async Task MarkAsRead(int id) { var allowcjange = nav.Uri.Split('/'); if (allowcjange.Length == 4 && (allowcjange[3].ToLower() == "chat" || string.IsNullOrEmpty(allowcjange[3]) )) { var msg = ChatCurrent.Responses.FirstOrDefault(m => m.ID == id); if (msg != null && !msg.IsRead && msg.Type == Common.Enums.ConversationType.UE) { msg.IsRead = true; await chatService.MarkAsReadChatItemAsync(id); } // StateHasChanged(); await Task.CompletedTask; } } async Task onclickAttachedto() { Dictionary parameters = new Dictionary(); parameters.Add("chatID", ChatCurrent.ID); parameters.Add("OnMultipleOfThree", EventCallback.Factory.Create(this, CallBackAttachedto)); await modal.ShowAsync("پیوست کارشناس", parameters: parameters); } async Task CallBackAttachedto() { await modal.HideAsync(); toastService.Notify(new ToastMessage(ToastType.Success, "کارشناس جدید به این گفتگو پیوست")); } async Task OpenChat() { if (CurrentUser.Role == "Company" || CurrentUser.Role == "Exper" && ChatCurrent.ExperID == CurrentUser.ExperID) { if (ChatCurrent.status != Common.Enums.ConversationStatus.Finished) return; if (await chatService.OpenChat(ChatCurrent.ID)) { ChatCurrent.status = Common.Enums.ConversationStatus.InProgress; StateHasChanged(); } else toastService.Notify(new ToastMessage(ToastType.Danger, "تغییر وضعیت گفتگو موفق نبود")); } else toastService.Notify(new ToastMessage(ToastType.Danger, "دسترسی به این گفتگو ندارید")); } async Task CloseChat() { if (ChatCurrent.status == Common.Enums.ConversationStatus.Finished) return; var options = new ConfirmDialogOptions { YesButtonText = "بله", YesButtonColor = ButtonColor.Success, NoButtonText = "انصراف", NoButtonColor = ButtonColor.Danger }; var confirmation = await dialog.ShowAsync( title: "پایان دادن به گفتگو", message1: "اطمینان دارید ؟", confirmDialogOptions: options); if (confirmation) { if (await chatService.ChatIsFinish(ChatCurrent.ID)) { ChatCurrent.status = Common.Enums.ConversationStatus.Finished; StateHasChanged(); } } } private static string GetImageDataUrl(string? fileType, byte[]? content) => (string.IsNullOrWhiteSpace(fileType) || content == null || content.Length == 0) ? string.Empty : $"data:{fileType};base64,{Convert.ToBase64String(content)}"; private static string GetDownloadFileName(string? fileName, string? fileType) { if (!string.IsNullOrWhiteSpace(fileName)) return fileName; var ext = ""; if (!string.IsNullOrWhiteSpace(fileType) && fileType.StartsWith("image/")) { ext = "." + fileType.Split('/').Last(); } return $"image_{DateTimeOffset.Now.ToUnixTimeSeconds()}{ext}"; } private string GetAudioDataUrl(string? fileType, byte[]? content) => (string.IsNullOrWhiteSpace(fileType) || content == null || content.Length == 0) ? string.Empty : $"data:{fileType};base64,{Convert.ToBase64String(content)}"; private string GetAudioDuration(byte[]? content) { // Simple duration calculation based on file size (approximate) if (content == null || content.Length == 0) return "00:00"; // Assuming 16-bit PCM at 44.1kHz, mono var bytesPerSecond = 44100 * 2; // 44.1kHz * 2 bytes per sample var durationSeconds = content.Length / bytesPerSecond; var minutes = durationSeconds / 60; var seconds = durationSeconds % 60; return $"{minutes:D2}:{seconds:D2}"; } }