mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-04-11 19:11:38 +00:00
287 lines
7.8 KiB
TypeScript
287 lines
7.8 KiB
TypeScript
import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
|
|
import { NgForm } from '@angular/forms';
|
|
import { HttpClient } from '@angular/common/http';
|
|
|
|
import { Subject } from 'rxjs';
|
|
import { takeUntil } from 'rxjs/operators';
|
|
|
|
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
|
|
import { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
|
|
import { ChatPanelService } from 'app/layout/components/chat-panel/chat-panel.service';
|
|
|
|
@Component({
|
|
selector : 'chat-panel',
|
|
templateUrl : './chat-panel.component.html',
|
|
styleUrls : ['./chat-panel.component.scss'],
|
|
encapsulation: ViewEncapsulation.None
|
|
})
|
|
export class ChatPanelComponent implements OnInit, AfterViewInit, OnDestroy
|
|
{
|
|
contacts: any[];
|
|
chat: any;
|
|
selectedContact: any;
|
|
sidebarFolded: boolean;
|
|
user: any;
|
|
|
|
@ViewChild('replyForm')
|
|
set replyForm(content: NgForm)
|
|
{
|
|
this._replyForm = content;
|
|
}
|
|
|
|
@ViewChild('replyInput')
|
|
set replyInput(content: ElementRef)
|
|
{
|
|
this._replyInput = content;
|
|
}
|
|
|
|
@ViewChildren(FusePerfectScrollbarDirective)
|
|
private _fusePerfectScrollbarDirectives: QueryList<FusePerfectScrollbarDirective>;
|
|
|
|
// Private
|
|
private _chatViewScrollbar: FusePerfectScrollbarDirective;
|
|
private _replyForm: NgForm;
|
|
private _replyInput: ElementRef;
|
|
private _unsubscribeAll: Subject<any>;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param {ChatPanelService} _chatPanelService
|
|
* @param {HttpClient} _httpClient
|
|
* @param {FuseSidebarService} _fuseSidebarService
|
|
*/
|
|
constructor(
|
|
private _chatPanelService: ChatPanelService,
|
|
private _httpClient: HttpClient,
|
|
private _fuseSidebarService: FuseSidebarService
|
|
)
|
|
{
|
|
// Set the defaults
|
|
this.selectedContact = null;
|
|
this.sidebarFolded = true;
|
|
|
|
// Set the private defaults
|
|
this._unsubscribeAll = new Subject();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
// @ Lifecycle hooks
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* On init
|
|
*/
|
|
ngOnInit(): void
|
|
{
|
|
// Load the contacts
|
|
this._chatPanelService.loadContacts().then(() => {
|
|
|
|
this.contacts = this._chatPanelService.contacts;
|
|
this.user = this._chatPanelService.user;
|
|
});
|
|
|
|
// Subscribe to the foldedChanged observable
|
|
this._fuseSidebarService.getSidebar('chatPanel').foldedChanged
|
|
.pipe(takeUntil(this._unsubscribeAll))
|
|
.subscribe((folded) => {
|
|
this.sidebarFolded = folded;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* After view init
|
|
*/
|
|
ngAfterViewInit(): void
|
|
{
|
|
this._chatViewScrollbar = this._fusePerfectScrollbarDirectives.find((directive) => {
|
|
return directive.elementRef.nativeElement.id === 'messages';
|
|
});
|
|
}
|
|
|
|
/**
|
|
* On destroy
|
|
*/
|
|
ngOnDestroy(): void
|
|
{
|
|
// Unsubscribe from all subscriptions
|
|
this._unsubscribeAll.next();
|
|
this._unsubscribeAll.complete();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
// @ Private methods
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Prepare the chat for the replies
|
|
*/
|
|
private _prepareChatForReplies(): void
|
|
{
|
|
setTimeout(() => {
|
|
|
|
// Reset the reply form
|
|
this._replyForm.reset();
|
|
|
|
// Focus to the reply input
|
|
// this._replyInput.nativeElement.focus();
|
|
|
|
// Scroll to the bottom of the messages list
|
|
if ( this._chatViewScrollbar )
|
|
{
|
|
this._chatViewScrollbar.update();
|
|
|
|
setTimeout(() => {
|
|
this._chatViewScrollbar.scrollToBottom(0);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
// @ Public methods
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Fold the temporarily unfolded sidebar back
|
|
*/
|
|
foldSidebarTemporarily(): void
|
|
{
|
|
this._fuseSidebarService.getSidebar('chatPanel').foldTemporarily();
|
|
}
|
|
|
|
/**
|
|
* Unfold the sidebar temporarily
|
|
*/
|
|
unfoldSidebarTemporarily(): void
|
|
{
|
|
this._fuseSidebarService.getSidebar('chatPanel').unfoldTemporarily();
|
|
}
|
|
|
|
/**
|
|
* Toggle sidebar opened status
|
|
*/
|
|
toggleSidebarOpen(): void
|
|
{
|
|
this._fuseSidebarService.getSidebar('chatPanel').toggleOpen();
|
|
}
|
|
|
|
/**
|
|
* Decide whether to show or not the contact's avatar in the message row
|
|
*
|
|
* @param message
|
|
* @param i
|
|
* @returns {boolean}
|
|
*/
|
|
shouldShowContactAvatar(message, i): boolean
|
|
{
|
|
return (
|
|
message.who === this.selectedContact.id &&
|
|
((this.chat.dialog[i + 1] && this.chat.dialog[i + 1].who !== this.selectedContact.id) || !this.chat.dialog[i + 1])
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check if the given message is the first message of a group
|
|
*
|
|
* @param message
|
|
* @param i
|
|
* @returns {boolean}
|
|
*/
|
|
isFirstMessageOfGroup(message, i): boolean
|
|
{
|
|
return (i === 0 || this.chat.dialog[i - 1] && this.chat.dialog[i - 1].who !== message.who);
|
|
}
|
|
|
|
/**
|
|
* Check if the given message is the last message of a group
|
|
*
|
|
* @param message
|
|
* @param i
|
|
* @returns {boolean}
|
|
*/
|
|
isLastMessageOfGroup(message, i): boolean
|
|
{
|
|
return (i === this.chat.dialog.length - 1 || this.chat.dialog[i + 1] && this.chat.dialog[i + 1].who !== message.who);
|
|
}
|
|
|
|
/**
|
|
* Toggle chat with the contact
|
|
*
|
|
* @param contact
|
|
*/
|
|
toggleChat(contact): void
|
|
{
|
|
// If the contact equals to the selectedContact,
|
|
// that means we will deselect the contact and
|
|
// unload the chat
|
|
if ( this.selectedContact && contact.id === this.selectedContact.id )
|
|
{
|
|
// Reset
|
|
this.resetChat();
|
|
}
|
|
// Otherwise, we will select the contact, open
|
|
// the sidebar and start the chat
|
|
else
|
|
{
|
|
// Unfold the sidebar temporarily
|
|
this.unfoldSidebarTemporarily();
|
|
|
|
// Set the selected contact
|
|
this.selectedContact = contact;
|
|
|
|
// Load the chat
|
|
this._chatPanelService.getChat(contact.id).then((chat) => {
|
|
|
|
// Set the chat
|
|
this.chat = chat;
|
|
|
|
// Prepare the chat for the replies
|
|
this._prepareChatForReplies();
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove the selected contact and unload the chat
|
|
*/
|
|
resetChat(): void
|
|
{
|
|
// Set the selected contact as null
|
|
this.selectedContact = null;
|
|
|
|
// Set the chat as null
|
|
this.chat = null;
|
|
}
|
|
|
|
/**
|
|
* Reply
|
|
*/
|
|
reply(event): void
|
|
{
|
|
event.preventDefault();
|
|
|
|
if ( !this._replyForm.form.value.message )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Message
|
|
const message = {
|
|
who : this.user.id,
|
|
message: this._replyForm.form.value.message,
|
|
time : new Date().toISOString()
|
|
};
|
|
|
|
// Add the message to the chat
|
|
this.chat.dialog.push(message);
|
|
|
|
// Update the server
|
|
this._chatPanelService.updateChat(this.chat.id, this.chat.dialog).then(response => {
|
|
|
|
// Prepare the chat for the replies
|
|
this._prepareChatForReplies();
|
|
});
|
|
}
|
|
}
|