Newer
Older
Undo / BlazorClient / Pages / Index.razor
@Derek Comartin Derek Comartin on 28 Mar 2023 2 KB Init
@page "/"
@using UndoExample
@using Microsoft.AspNetCore.SignalR.Client
@using System.Collections.Concurrent
@inject IMessageSession MessageSession
@inject NavigationManager Navigation

<PageTitle>Index</PageTitle>

<div class="container">
    
    <div class="mb-3">
         <textarea class="form-control" @bind="NewMessage"></textarea>
    </div>
    <div class="mb-3">
        <button class="btn btn-primary" @onclick="SendNow">Send Now</button>
        <button class="btn btn-primary" @onclick="SendWithDelay">Send with Delay</button>
    </div>

    @foreach (var tweet in _tweets)
    {
        <div class="alert alert-primary alert-dismissible fade show" role="alert">
            @tweet.Message
            @if (tweet.CanUndo)
            {
                <button type="button" class="btn-close" data-bs-dismiss="alert" @onclick="() => UndoTweet(tweet.TweetId)" aria-label="Close"></button>
            }
        </div>
    }

</div>

@code {

    private record ClientTweet(Guid TweetId, string Message, bool CanUndo);
    
    private HubConnection? _hubConnection;
    private readonly ConcurrentBag<ClientTweet> _tweets = new();
    private string NewMessage { get; set; } = "";
    
    protected override async Task OnInitializedAsync()
    {
        _hubConnection = new HubConnectionBuilder()
            .WithUrl(Navigation.ToAbsoluteUri("/tweethub"))
            .Build();

        _hubConnection.On<Guid, string>("tweeted", (tweetId, message) =>
        {
            RemoveTweet(tweetId);
            _tweets.Add(new ClientTweet(tweetId, message, false));
            
            InvokeAsync(StateHasChanged);
        });
        
        _hubConnection.On<Guid>("undone", (tweetId) =>
        {
            RemoveTweet(tweetId);
            InvokeAsync(StateHasChanged);
        });

        await _hubConnection.StartAsync();
    }

    private void RemoveTweet(Guid tweetId)
    {
        var existingTweet = _tweets.SingleOrDefault(x => x.TweetId == tweetId);
        if (existingTweet != null)
        {
            _tweets.TryTake(out existingTweet);
        }
    }
    
    private async Task SendNow()
    {
        await MessageSession.Send(new Tweet(Guid.NewGuid(), NewMessage));
        NewMessage = string.Empty;
    }
    
    private async Task SendWithDelay()
    {
        var tweet = new TweetWithDelay(Guid.NewGuid(), NewMessage);
        await MessageSession.Send(tweet);
        _tweets.Add(new ClientTweet(tweet.TweetId, tweet.Message, true));
        NewMessage = string.Empty;
    }

    private async Task UndoTweet(Guid tweetId)
    {
        await MessageSession.Send(new UndoTweet(tweetId));
    }
}