rpaschoal / ng-chat

💬 A simple facebook/linkedin lookalike chat module for Angular applications.
MIT License
155 stars 92 forks source link

When two participant chat, first message trigger the chat window of second participant to be opened but message not delivered, after second message, message get delivered #161

Closed glglak closed 4 years ago

glglak commented 4 years ago

I am following copy/paste examples with simple tweaks to the backend, and I got an issue that message on chat first time get delivered to the participant and the chat window open but the message doesn't appear, after the second message from participant A, the messages start to appear on chat windows

Type Script Implementation

import { ChatAdapter, IChatGroupAdapter, User, Group, Message, ChatParticipantStatus, ParticipantResponse, ParticipantMetadata, ChatParticipantType, IChatParticipant } from 'ng-chat';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

import * as signalR from "@aspnet/signalr";
import { Utilities } from './utilities';

export class SignalRGroupAdapter extends ChatAdapter implements IChatGroupAdapter {
  public userId: string;

  private hubConnection: signalR.HubConnection
  public static serverBaseUrl: string = 'https://localhost:5001/'; // Set this to 'https://localhost:5001/' if running locally

  constructor(private username: string, private http: HttpClient) {
    super();

    this.initializeConnection();
  }

  private initializeConnection(): void {
    this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl(`${SignalRGroupAdapter.serverBaseUrl}chathub`, {
        skipNegotiation: false,
        transport: signalR.HttpTransportType.WebSockets
      })
      .build();

    this.hubConnection
      .start()
      .then(() => {
        this.joinRoom();

        this.initializeListeners();
      }).catch(err => console.error(err.toString()));
   }

  private initializeListeners(): void {
    if (this.hubConnection && this.hubConnection.state == signalR.HubConnectionState.Connected) {

      this.hubConnection.on("generatedUserId", (userId) => {
        // With the userId set the chat will be rendered
        this.userId = userId;
      });

      this.hubConnection.on("messageReceived", (participant, message) => {
        // Handle the received message to ng-chat
        console.log('recieved message', message);
        this.onMessageReceived(participant, message);

      });

      this.hubConnection.on("friendsListChanged", (participantsResponse: Array<ParticipantResponse>) => {
        // Use polling for the friends list for this simple group example
        // If you want to use push notifications you will have to send filtered messages through your hub instead of using the "All" broadcast channel
        //this.onFriendsListChanged(participantsResponse.filter(x => x.participant.id != this.userId));

        // Handle the received response to ng-chat
        this.onFriendsListChanged(participantsResponse.filter(x => x.participant.id != this.userId));

      });
    }
  }

  joinRoom(): void {
    if (this.hubConnection && this.hubConnection.state == signalR.HubConnectionState.Connected) {
      this.hubConnection.send("join", Utilities.GetClinicId(), Utilities.GetUserId() );
    }
  }

  listFriends(): Observable<ParticipantResponse[]> {
    // List connected users to show in the friends list
    // Sending the userId from the request body as this is just a demo 
    return this.http
      .post(`${SignalRGroupAdapter.serverBaseUrl}api/chat/${Utilities.GetClinicId()}/${Utilities.GetUserId()}`, {})
      .pipe(
        map((res: any) => res),
        catchError((error: any) => Observable.throw(error.error || 'Server error'))
      );
  }

  getMessageHistory(destinataryId: any): Observable<Message[]> {
    // This could be an API call to your web application that would go to the database
    // and retrieve a N amount of history messages between the users.
    return of([]);
  }

  sendMessage(message: Message): void {
    if (this.hubConnection && this.hubConnection.state == signalR.HubConnectionState.Connected)
      console.log('hub connected send message', message); 
    this.hubConnection.send("sendMessage", message);
  }

  groupCreated(group: Group): void {
    this.hubConnection.send("groupCreated", group);
  }

}

Chat hub Implementation

  public async Task Join(string clinicId,string userId)
    {

        var currentUser =await _userRepository.GetUserById(userId);
         lock (ParticipantsConnectionLock)
        {
            AllConnectedParticipants.Add(new ParticipantResponseViewModel()
            {
                Metadata = new ParticipantMetadataViewModel()
                {
                    TotalUnreadMessages = 0
                },
                Participant = new ChatParticipantViewModel()
                {
                    DisplayName = currentUser.FullName,
                    Id = currentUser.Id,
                    ConnectionId=Context.ConnectionId,
                    Status=1,
                    Avatar=currentUser.ProfilePic,
                    ParticipantType=0
                }
            });
             // This will be used as the user's unique ID to be used on ng-chat as the connected user.
            // You should most likely use another ID on your application
            Clients.Caller.SendAsync("generatedUserId", currentUser.Id);
            Clients.All.SendAsync("friendsListChanged", AllConnectedParticipants);

        }
    }

    public void SendMessage(MessageViewModel message)
    {
        var sender = AllConnectedParticipants.Find(x => x.Participant.Id == message.FromId);
        var reciever = AllConnectedParticipants.Find(x => x.Participant.Id == message.ToId);
        if (sender != null)
        {
            Clients.Client(reciever.Participant.ConnectionId).SendAsync("messageReceived", sender.Participant, message);
        }
    }
rpaschoal commented 4 years ago

Hi @glglak ,

You haven't implemented the getMessageHistory method for what I can see. Are you sure you have the historyEnabled option disabled?

By design if you do want to use history on chat windows, it will not push the initial message and assume that it will be fetched with the getMessageHistory call.