Skip to content

Commit

Permalink
split chat into more components
Browse files Browse the repository at this point in the history
  • Loading branch information
NielsPilgaard committed Aug 17, 2024
1 parent cb7f943 commit 912e0a3
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 156 deletions.
219 changes: 182 additions & 37 deletions src/web/Jordnaer/Features/Chat/ChatMessageList.razor
Original file line number Diff line number Diff line change
@@ -1,50 +1,120 @@
@inject CurrentUser CurrentUser

<MudVirtualize Items="ActiveChat?.Messages" Context="message" OverscanCount="8" ItemSize="80">
@inject IChatService ChatService
@inject IChatMessageCache ChatMessageCache
@inject IProfileCache ProfileCache
@inject IJSRuntime JsRuntime
@inject ChatSignalRClient ChatSignalRClient
@inject NavigationManager Navigation

@if (IsMessageFromSelf(message))
{
<MudListItem Class="message-from-self" T="MudTooltip">
<MudTooltip Placement="Placement.Top" ShowOnClick ShowOnHover="false" ShowOnFocus="false" Arrow Text="@message.SentUtc.DisplayExactTime()">
<MudTooltip ShowOnHover Arrow Text="@message.SentUtc.DisplayTimePassed()">
<MudChip Class="chat-chip" Size="Size.Large" T="MudText">
<MudText Typo="Typo.h6">@message.Text</MudText>
</MudChip>
</MudTooltip>
</MudTooltip>
</MudListItem>
}
else
@attribute [Authorize]

@if (ActiveChat is null)
{
<MudText>Der er ingen chat valgt</MudText>
return;
}

<MudItem Class="chat-message-window" xs="12" sm="12" md="8" lg="8" xl="8" xxl="8">
@if (IsMobile)
{
<MudListItem T="MudTooltip">
<MudTooltip Placement="Placement.Top" ShowOnClick ShowOnHover="false" ShowOnFocus="false" Arrow Text="@message.SentUtc.DisplayExactTime()">
<MudTooltip ShowOnHover Arrow Text="@message.SentUtc.DisplayTimePassed()">
<MudChip Class="chat-chip" Size="Size.Large" T="MudLink">
<AvatarContent>
@if (!NextMessageIsFromSameSender(message))
{
<MudLink Href="@GetRecipientsUserName(message)">
<MudAvatar>
<MudImage Src="@GetRecipientsProfilePictureUrl(message)" loading="lazy" Alt="Avatar" />
</MudAvatar>
</MudLink>
}
</AvatarContent>
<ChildContent>
<MudText Typo="Typo.h6">@message.Text</MudText>
</ChildContent>
</MudChip>
</MudTooltip>
</MudTooltip>
</MudListItem>
<MudAppBar Dense
ToolBarClass="justify-space-between h-100"
Color="Color.Primary"
Elevation="5">
<MudFab StartIcon="@Icons.Material.Filled.ArrowBack"
OnClick="BackToList"
Color="Color.Info"
Size="Size.Small" />
<MudText Typo="Typo.h5">@ActiveChat.GetDisplayName(CurrentUser.Id!)</MudText>
</MudAppBar>
}
</MudVirtualize>

<MudList Class="chat-message-list" Padding="false" ReadOnly Dense T="RenderFragment">
<MudSpacer />
<MudVirtualize Items="ActiveChat?.Messages" Context="message" OverscanCount="8" ItemSize="80">

@if (IsMessageFromSelf(message))
{
<MudListItem Class="message-from-self" T="MudTooltip">
<MudTooltip Placement="Placement.Top" ShowOnClick ShowOnHover="false" ShowOnFocus="false" Arrow Text="@message.SentUtc.DisplayExactTime()">
<MudTooltip ShowOnHover Arrow Text="@message.SentUtc.DisplayTimePassed()">
<MudChip Class="chat-chip" Size="Size.Large" T="MudText">
<MudText Typo="Typo.h6">@message.Text</MudText>
</MudChip>
</MudTooltip>
</MudTooltip>
</MudListItem>
}
else
{
<MudListItem T="MudTooltip">
<MudTooltip Placement="Placement.Top" ShowOnClick ShowOnHover="false" ShowOnFocus="false" Arrow Text="@message.SentUtc.DisplayExactTime()">
<MudTooltip ShowOnHover Arrow Text="@message.SentUtc.DisplayTimePassed()">
<MudChip Class="chat-chip" Size="Size.Large" T="MudLink">
<AvatarContent>
@if (!NextMessageIsFromSameSender(message))
{
<MudLink Href="@GetRecipientsUserName(message)">
<MudAvatar>
<MudImage Src="@GetRecipientsProfilePictureUrl(message)" loading="lazy" Alt="Avatar" />
</MudAvatar>
</MudLink>
}
</AvatarContent>
<ChildContent>
<MudText Typo="Typo.h6">@message.Text</MudText>
</ChildContent>
</MudChip>
</MudTooltip>
</MudTooltip>
</MudListItem>
}
</MudVirtualize>

@if (LastMessageWasSentSuccessfullyByCurrentUser)
{
<div title="Din besked er blevet sendt" class="message-sent-successfully-container">
<MudIcon Icon="@Icons.Material.Outlined.CheckCircleOutline"
Class="message-sent-successfully" />
</div>
}

<MudTextField id="chat-message-input"
@ref="_messageInput"
T="string"
FullWidth
Immediate
Clearable
AutoFocus
Adornment="Adornment.End"
OnKeyDown="SendMessageOnEnter"
AdornmentIcon="@Icons.Material.Filled.Send"
AdornmentColor="@(string.IsNullOrWhiteSpace(_messageInput.Value) ? Color.Default : Color.Primary)"
OnAdornmentClick="SendMessage"
Class="mt-3"
Lines="3"
IconSize="Size.Large"
Style="@($"background: {JordnaerTheme.CustomTheme.PaletteLight.BackgroundGray}")" />
</MudList>
</MudItem>
@code
{
[Parameter]
[Parameter, EditorRequired]
public required ChatDto? ActiveChat { get; set; }

[Parameter]
public EventCallback<ChatDto?> ActiveChatChanged { get; set; }

[Parameter, EditorRequired]
public bool IsMobile { get; set; }

[Parameter, EditorRequired]
public bool LastMessageWasSentSuccessfullyByCurrentUser { get; set; }

private MudTextField<string> _messageInput = new();
private bool _isActiveChatPublished => ActiveChat?.Messages.Count is not 0;

private bool IsMessageFromSelf(ChatMessageDto message) => message.SenderId == CurrentUser.Id;

private string GetRecipientsProfilePictureUrl(ChatMessageDto message)
Expand Down Expand Up @@ -76,4 +146,79 @@

return ActiveChat.Messages[messageIndex + 1].SenderId == message.SenderId;
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await ScrollToBottom();
}

private void MarkMessageIfSuccessfullySentByCurrentUser()
{
if (ActiveChat is null)
{
return;
}

var lastMessage = ActiveChat.Messages.LastOrDefault();
if (lastMessage is null)
{
LastMessageWasSentSuccessfullyByCurrentUser = false;
return;
}

LastMessageWasSentSuccessfullyByCurrentUser = lastMessage.SenderId == CurrentUser.Id;
}

private async ValueTask ScrollToBottom() => await JsRuntime.InvokeVoidAsyncWithErrorHandling("scrollFunctions.scrollToBottomOfElement", ".chat-message-window");

private async Task BackToList()
{
ActiveChat = null;
await ActiveChatChanged.InvokeAsync(ActiveChat);
await JsRuntime.GoBackAsync();
}

private async Task SendMessage()
{
if (ActiveChat is null || string.IsNullOrWhiteSpace(_messageInput.Value))
{
return;
}

var message = new ChatMessageDto
{
ChatId = ActiveChat.Id,
Id = NewId.NextGuid(),
SentUtc = DateTime.UtcNow,
SenderId = CurrentUser.Id!,
Text = _messageInput.Value
};

await _messageInput.BlurAsync();
await _messageInput.Clear();

ActiveChat.Messages.Add(message);

if (_isActiveChatPublished)
{
await ChatService.SendMessageAsync(message);
}
else
{
await ChatService.StartChatAsync(ActiveChat.ToStartChatCommand(CurrentUser.Id!));
}

await _messageInput.FocusAsync();
await ScrollToBottom();
}

// TODO: Add MudScrollToTop that shows when user is scrolled up in the chat window
private async Task SendMessageOnEnter(KeyboardEventArgs keyboardEventArgs)
{
if (keyboardEventArgs is { Key: "Enter", ShiftKey: false })
{
await SendMessage();
}
}
}
Loading

0 comments on commit 912e0a3

Please sign in to comment.