rpaschoal / ng-chat

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

Open chat window for an individual direclty, instead of listing all friends #108

Closed hsrashmi closed 5 years ago

hsrashmi commented 5 years ago

Hi, I've a requirement in which my GUI itself has list of friends. So, using ng-chat, is it possible to open chat window for selected the user directly, without ng-chat showing list of friends. Regards, Rashmi

rpaschoal commented 5 years ago

Hi @hsrashmi ,

Yes it is possible, you can set hideFriendsList to true and control ng-chat using the IChatController interface. Both of these options are described in detail on the README of this repository. Let me know if you've managed to get it working on your application 😸

Kolpak86 commented 5 years ago

Hi @rpaschoal, can you make some example control ng-chat using the IChatController interface?

rpaschoal commented 5 years ago

Hi @Kolpak86 ,

It is on the readme, you need to add an angular identifier to your ng-chat usage:

<ng-chat #ngChatInstance ... />

Then on your component TS code (assuming you are using TypeScript):

@ViewChild('ngChatInstance') protected ngChatInstance: IChatController;

Make sure you import IChatController from the ng-chat package at the top.

After you've done the above, you will be able to trigger some behavior from ng-chat through the ngChatInstance. Example:

this.ngChatInstance.triggerOpenChatWindow(user);

This is what you can do using the IChatController interface:

Here is the interface definition: https://github.com/rpaschoal/ng-chat/blob/master/src/ng-chat/core/chat-controller.ts

Kolpak86 commented 5 years ago

app.component.html: <ng-chat #ngChatInstance [adapter]="adapter" [userId]="999" [title]="'Онлайн операторы'" [historyEnabled]="true" [historyPageSize]="4" [messagePlaceholder]="'Задайте вопрос'" [hideFriendsList]="true" [searchEnabled]="false" (onMessagesSeen)="messageSeen($event)">

app.componet.ts: import { Component, ViewChild, OnInit } from '@angular/core'; import { ChatAdapter, IChatController, User} from 'ng-chat'; import { DemoAdapter } from './demo-adapter'; @Component({ selector: 'app-root', templateUrl: './app.component.html', }) export class AppComponent implements OnInit { @ViewChild('ngChatInstance') protected ngChatInstance: IChatController; public adapter: ChatAdapter = new DemoAdapter();

ngOnInit() { this.ngChatInstance.triggerOpenChatWindow(user); }

public messageSeen(event: any) { console.log(event); } }

Any advice?: image

hsrashmi commented 5 years ago

Hi @hsrashmi ,

Yes it is possible, you can set hideFriendsList to true and control ng-chat using the IChatController interface. Both of these options are described in detail on the README of this repository. Let me know if you've managed to get it working on your application

@rpaschoal, i missed to see it in read me, it indeed worked. Thanks for the quick reply

Kolpak86 commented 5 years ago

@hsrashmi could you please share a piece of your code where you use ihatController?

hsrashmi commented 5 years ago

@Kolpak86, its same as mentioned by @rpaschoal in his reply.

And, your code looks fine and should work. What is it displaying?

In my template, I'm opening chat window when a chat icon on the screen is clicked. So, on click event i'm calling a function "openChat(user name)" as below.

      <ng-chat #ngChatInstance
       [adapter]="adapter"
       [groupAdapter]="adapter"
       [userId]="data.contact_id"
       [historyEnabled]="true"
       [historyPageSize]="4"
       [hideFriendsList]="true"
      </ng-chat>

In my component class, i've this:

@ViewChild('ngChatInstance') protected ngChatInstance: IChatController;

openChat(contactId){ console.log('openChat clicked'); this.ngChatInstance.triggerOpenChatWindow(contactId); }

Kolpak86 commented 5 years ago

@hsrashmi thanks a lot bro:)

rpaschoal commented 5 years ago

I'm confused, have you guys managed to get it working? 🤣 @Kolpak86 , @hsrashmi

Kolpak86 commented 5 years ago

@rpaschoal yes it works 👍

hsrashmi commented 5 years ago

Hi @Kolpak86 , i was able to get the chat window up for single participant with the code you pointed out. Thanks for that. But there seems to be another issue. Not sure if I should have it as a separate issue.

This is what it is. A message is sent from the opened chat window, let's say with userId = 2

In template, i've this: <i class="fa fa-comment-o fa-lg" (click)="openChat(i)"> <ng-chat #ngChatInstance [adapter]="adapter" [userId]=2 [historyEnabled]="true" [historyPageSize]="4" [hideFriendsList]="true" (onParticipantClicked)="onEventTriggered('ParticipantClicked triggered')" (onParticipantChatOpened)="onEventTriggered('ParticipantChatOpened triggered')" (onParticipantChatClosed)="onEventTriggered('ParticipantChatClosed triggered')" (onMessagesSeen)="onEventTriggered('MessageSeen triggered')">

Component class has this: openChat(i){ let user = { participantType: ChatParticipantType.User, id: 1, displayName: "Daenerys Targaryen", avatar: "https://68.media.tumblr.com/avatar_d28d7149f567_128.png", status: ChatParticipantStatus.Busy }; console.log('openChat clicked'); this.ngChatInstance.triggerOpenChatWindow(user); }

Adapter class has this: sendMessage(message: Message): void { console.log(message); let replyMessage = new Message(); replyMessage.message = "You have typed '" + message.message + "'"; replyMessage.dateSent = new Date(); replyMessage.fromId = message.toId; replyMessage.toId = message.fromId; console.log(replyMessage); let user = this.mockedParticipants.find(x => x.id == replyMessage.fromId); this.onMessageReceived(user, replyMessage);
}

As you can see, when a message is sent an auto reply will be sent back (used same code as your demo example adapter). But when this reply is received it opens a new chat window instead of showing in the same window. this happens only for the first time. later, all subsequent messages in the new window happens fine. Please let me know how to fix this? Let me know, if i'm not clear, i'll try to rephrase my question.

Adding the images, if it helps. Basically first chat window is not getting recognized by the library image

image

image

Regards, Rashmi

hsrashmi commented 5 years ago

Hello Andrew, Any update on the above issue?

Regards, Rashmi

Kolpak86 commented 5 years ago

Hello, @hsrashmi. Sorry I have one problem with building app. When I'll solve the problem then I'll look on that issue :)

hsrashmi commented 5 years ago

Sure, do let me know when you have any updates on this one. i need to get my chat app working asap

Kolpak86 commented 5 years ago

@hsrashmi. This how it works for me ezgif com-video-to-gif Do you need the same behavior?

hsrashmi commented 5 years ago

yes, i need the same behaviour. in my case, the reply mesg is coming in a new window instead of showing in same window. Is it possible to share your code?

Kolpak86 commented 5 years ago

app.componet.ts: import { Component, ChangeDetectorRef, ViewChild } from '@angular/core'; import { ChatAdapter, IChatController, User, ChatParticipantType, ChatParticipantStatus } from 'ng-chat'; import { Adapter } from './adapter'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) export class AppComponent { @ViewChild('ngChatInstance') protected ngChatInstance: IChatController; public user = { participantType: ChatParticipantType.User, id: 1, displayName: 'Онлайн оператор', avatar: 'https://66.media.tumblr.com/avatar_9dd9bb497b75_128.pnj', status: ChatParticipantStatus.Online, }; public adapter: ChatAdapter = new Adapter(); public fileUploadUrl = 'https://ng-chat-api.azurewebsites.net/UploadFile'; public show = false; public userId = 999; constructor(private cd: ChangeDetectorRef) {} // tslint:disable-next-line: use-life-cycle-interface ngAfterViewInit() { this.cd.detectChanges(); } public messageSeen(event: any) { console.log(event); }

public closeChat(event: any) { this.show = true; } public showChat(event: any) { this.show = false; } public openChat(user: User) { this.ngChatInstance.triggerOpenChatWindow(user); } }

app.component.html: <button *ngIf="!show" class="button" (click)="openChat(user)">Онлайн поддержка <ng-chat #ngChatInstance [adapter]="adapter" [userId]="userId" [historyEnabled]="true" [historyPageSize]="4" [messagePlaceholder]="'Задайте вопрос'" [hideFriendsList]="true" [searchEnabled]="false" [fileUploadUrl]="fileUploadUrl" [messageDatePipeFormat]="'dd.MM.yyyy HH:mm:ss'" (onMessagesSeen)="messageSeen($event)" (onParticipantChatOpened)="closeChat($event)" (onParticipantChatClosed)="showChat($event)">

Kolpak86 commented 5 years ago

But this is only test.

hsrashmi commented 5 years ago

Can you please also share adapter code?

Kolpak86 commented 5 years ago

import { ChatAdapter, IChatGroupAdapter, User, Group, Message, ChatParticipantStatus, ParticipantResponse, ParticipantMetadata, ChatParticipantType, IChatParticipant, } from 'ng-chat'; import { Observable, of } from 'rxjs'; import { delay } from 'rxjs/operators';

export class Adapter extends ChatAdapter implements IChatGroupAdapter { public static mockedParticipants: IChatParticipant[] = [ { participantType: ChatParticipantType.User, id: 1, displayName: 'Онлайн оператор', avatar: 'https://66.media.tumblr.com/avatar_9dd9bb497b75_128.pnj', status: ChatParticipantStatus.Online, }, ];

listFriends(): Observable<ParticipantResponse[]> { return of( Adapter.mockedParticipants.map(user => { const participantResponse = new ParticipantResponse();

    participantResponse.participant = user;
    participantResponse.metadata = {
      totalUnreadMessages: Math.floor(Math.random() * 10),
    };

    return participantResponse;
  }),
);

}

getMessageHistory(destinataryId: any): Observable<Message[]> { let mockedHistory: Array;

mockedHistory = [
  {
    fromId: 1,
    toId: 999,
    message: 'Добрый день!',
    dateSent: new Date(),
  },
];

return of(mockedHistory).pipe(delay(2000));

}

sendMessage(message: Message): void { setTimeout(() => { const replyMessage = new Message();

  replyMessage.message = 'You have typed ' + message.message + ' ';
  replyMessage.dateSent = new Date();

  if (isNaN(message.toId)) {
    const group = Adapter.mockedParticipants.find(x => x.id === message.toId) as Group;

    // Message to a group. Pick up any participant for this
    const randomParticipantIndex = Math.floor(Math.random() * group.chattingTo.length);
    replyMessage.fromId = group.chattingTo[randomParticipantIndex].id;

    replyMessage.toId = message.toId;

    this.onMessageReceived(group, replyMessage);
  } else {
    replyMessage.fromId = message.toId;
    replyMessage.toId = message.fromId;

    const user = Adapter.mockedParticipants.find(x => x.id === replyMessage.fromId);

    this.onMessageReceived(user, replyMessage);
  }
}, 1000);

}

groupCreated(group: Group): void { Adapter.mockedParticipants.push(group);

Adapter.mockedParticipants = Adapter.mockedParticipants.sort((first, second) =>
  second.displayName > first.displayName ? -1 : 1,
);

// Trigger update of friends list
this.listFriends().subscribe(response => {
  this.onFriendsListChanged(response);
});

} } But this is only test code

hsrashmi commented 5 years ago

Thanks for the code, will check and come back on this

hsrashmi commented 5 years ago

Hi @rpaschoal, Issue is still not resolved for me. I still get reply is different window. Do you have any suggestion?

rpaschoal commented 5 years ago

@hsrashmi Check your adapter and your hub, those are the key pieces who will target to whom the message is going to be sent to. Your issue might be something very simple like sending the message to the sender again instead of sending it to the desired receiver.

rpaschoal commented 5 years ago

Closing this as @Kolpak86 has managed to get the same behavior working and this thread hasn't had any interactions in a while.