mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-01-10 12:35:07 +00:00
(Chat Panel) Don't unfold the panel on hover
(Chat Panel) Always keep the contacts list in view
This commit is contained in:
parent
585709cf93
commit
e1c906f08b
|
@ -1,6 +1,6 @@
|
||||||
<div class="header mat-elevation-z4 mat-primary-bg" fxLayout="row" fxLayoutAlign="space-between center">
|
<div class="header mat-elevation-z4 mat-primary-bg" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
|
||||||
<ng-container *ngIf="view === 'contacts'">
|
<ng-container *ngIf="selectedContact === null">
|
||||||
|
|
||||||
<div class="title ml-16" fxLayout="row" fxLayoutAlign="start center">
|
<div class="title ml-16" fxLayout="row" fxLayoutAlign="start center">
|
||||||
<mat-icon class="s-32 white-fg">chat</mat-icon>
|
<mat-icon class="s-32 white-fg">chat</mat-icon>
|
||||||
|
@ -9,21 +9,17 @@
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="view === 'chat'">
|
<ng-container *ngIf="selectedContact !== null">
|
||||||
|
|
||||||
<div class="title" fxLayout="row" fxLayoutAlign="start center">
|
<div class="title" fxLayout="row" fxLayoutAlign="start center">
|
||||||
<button class="mx-8" mat-icon-button (click)="goToContacts()">
|
<img [src]="selectedContact.avatar" class="avatar mx-16">
|
||||||
<mat-icon>arrow_back</mat-icon>
|
<h3 class="text-truncate">{{selectedContact.name}}</h3>
|
||||||
</button>
|
|
||||||
<img [src]="contact.avatar" class="avatar mr-0 w-32 h-32">
|
|
||||||
<h3 class="ml-12 text-truncate">{{contact.name}}</h3>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<button mat-icon-button class="toggle-sidebar-folded mr-8" (click)="toggleSidebarFolded()" fxHide fxShow.gt-md>
|
<button mat-icon-button class="toggle-sidebar-folded mr-8" (click)="foldSidebarTemporarily()" fxHide fxShow.gt-md>
|
||||||
<mat-icon class="secondary-text s-20" *ngIf="sidebarFolded">lock_open</mat-icon>
|
<mat-icon class="secondary-text s-20">arrow_forward</mat-icon>
|
||||||
<mat-icon class="secondary-text s-20" *ngIf="!sidebarFolded">lock_outline</mat-icon>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-icon-button class="toggle-sidebar-folded mr-8" (click)="toggleSidebarOpen()" fxHide.gt-md>
|
<button mat-icon-button class="toggle-sidebar-folded mr-8" (click)="toggleSidebarOpen()" fxHide.gt-md>
|
||||||
|
@ -32,54 +28,57 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="view === 'contacts'">
|
<div>
|
||||||
|
|
||||||
|
<!-- Contacts -->
|
||||||
<mat-list id="contacts-list" fusePerfectScrollbar [fusePerfectScrollbarOptions]="{suppressScrollX: true}">
|
<mat-list id="contacts-list" fusePerfectScrollbar [fusePerfectScrollbarOptions]="{suppressScrollX: true}">
|
||||||
|
|
||||||
<mat-list-item *ngFor="let contact of contacts" [ngClass]="contact.status" (click)="goToChat(contact)"
|
<mat-list-item *ngFor="let contact of contacts"
|
||||||
|
[ngClass]="contact.status"
|
||||||
|
[class.active]="contact.id === selectedContact?.id"
|
||||||
|
(click)="goToChat(contact)"
|
||||||
|
[matTooltip]="contact.name"
|
||||||
|
matTooltipPosition="left"
|
||||||
matRipple>
|
matRipple>
|
||||||
|
|
||||||
<img matListAvatar [src]="contact.avatar">
|
<img matListAvatar [src]="contact.avatar">
|
||||||
|
|
||||||
<h3 matLine>
|
|
||||||
{{contact.name}}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div class="unread-count" *ngIf="contact.unread">{{contact.unread}}</div>
|
<div class="unread-count" *ngIf="contact.unread">{{contact.unread}}</div>
|
||||||
<div class="status-icon" [ngClass]="contact.status"></div>
|
<div class="status-icon" [ngClass]="contact.status"></div>
|
||||||
|
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
</mat-list>
|
</mat-list>
|
||||||
|
<!-- / Contacts -->
|
||||||
|
|
||||||
</ng-container>
|
<!-- Chat -->
|
||||||
|
|
||||||
<ng-container *ngIf="view === 'chat'">
|
|
||||||
|
|
||||||
<div id="chat" fxLayout="column" fxFlex="1 1 auto">
|
<div id="chat" fxLayout="column" fxFlex="1 1 auto">
|
||||||
|
|
||||||
<div class="messages" fxFlex="1 1 auto" fusePerfectScrollbar>
|
<div id="messages" class="messages" fxFlex="1 1 auto" fusePerfectScrollbar>
|
||||||
|
|
||||||
<div *ngFor="let message of chat.dialog; let i = index" class="message-row"
|
<ng-container *ngIf="chat && chat.dialog && chat.dialog.length > 0">
|
||||||
[ngClass]="{
|
|
||||||
|
<div *ngFor="let message of chat.dialog; let i = index" class="message-row"
|
||||||
|
[ngClass]="{
|
||||||
'me': message.who === user.id,
|
'me': message.who === user.id,
|
||||||
'contact': message.who !== user.id,
|
'contact': message.who !== user.id,
|
||||||
'first-of-group': isFirstMessageOfGroup(message, i),
|
'first-of-group': isFirstMessageOfGroup(message, i),
|
||||||
'last-of-group': isLastMessageOfGroup(message, i)
|
'last-of-group': isLastMessageOfGroup(message, i)
|
||||||
}">
|
}">
|
||||||
|
|
||||||
<img *ngIf="shouldShowContactAvatar(message, i)"
|
<img *ngIf="shouldShowContactAvatar(message, i)"
|
||||||
src="{{contact.avatar}}"
|
src="{{selectedContact.avatar}}"
|
||||||
class="avatar">
|
class="avatar">
|
||||||
|
|
||||||
|
<div class="bubble">
|
||||||
|
<div class="message">{{message.message}}</div>
|
||||||
|
<div class="time secondary-text">{{message.time | date:'short'}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="bubble">
|
|
||||||
<div class="message">{{message.message}}</div>
|
|
||||||
<div class="time secondary-text">{{message.time | date:'short'}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="chat.dialog.length === 0">
|
<ng-container *ngIf="chat && chat.dialog && chat.dialog.length === 0">
|
||||||
|
|
||||||
<div class="no-messages-icon">
|
<div class="no-messages-icon">
|
||||||
<mat-icon class="s-128">chat</mat-icon>
|
<mat-icon class="s-128">chat</mat-icon>
|
||||||
|
@ -115,5 +114,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- / Chat -->
|
||||||
|
|
||||||
</ng-container>
|
</div>
|
|
@ -4,9 +4,9 @@ chat-panel {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
width: 280px;
|
width: 360px;
|
||||||
min-width: 280px;
|
min-width: 360px;
|
||||||
max-width: 280px;
|
max-width: 360px;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
@ -31,11 +31,28 @@ chat-panel {
|
||||||
#contacts-list {
|
#contacts-list {
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
width: 72px;
|
||||||
|
min-width: 72px;
|
||||||
|
max-width: 72px;
|
||||||
|
|
||||||
|
// Perfect scrollbar
|
||||||
|
.ps__rail-y {
|
||||||
|
width: 3px !important;
|
||||||
|
|
||||||
|
.ps__thumb-y {
|
||||||
|
width: 3px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mat-list-item {
|
.mat-list-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: mat-color(mat-palette($mat-grey, 300));
|
||||||
|
@include mat-elevation(2);
|
||||||
|
}
|
||||||
|
|
||||||
&.offline {
|
&.offline {
|
||||||
|
|
||||||
.mat-list-item-content {
|
.mat-list-item-content {
|
||||||
|
@ -316,6 +333,9 @@ chat-panel {
|
||||||
fuse-sidebar {
|
fuse-sidebar {
|
||||||
|
|
||||||
&.chat-panel {
|
&.chat-panel {
|
||||||
|
width: 360px;
|
||||||
|
min-width: 360px;
|
||||||
|
max-width: 360px;
|
||||||
|
|
||||||
// Folded
|
// Folded
|
||||||
&.folded {
|
&.folded {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, ElementRef, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
|
||||||
import { NgForm } from '@angular/forms';
|
import { NgForm } from '@angular/forms';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
@ -15,20 +15,13 @@ import { ChatPanelService } from 'app/layout/components/chat-panel/chat-panel.se
|
||||||
styleUrls : ['./chat-panel.component.scss'],
|
styleUrls : ['./chat-panel.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class ChatPanelComponent implements OnInit, OnDestroy
|
export class ChatPanelComponent implements OnInit, AfterViewInit, OnDestroy
|
||||||
{
|
{
|
||||||
contacts: any[];
|
contacts: any[];
|
||||||
contact: any;
|
|
||||||
chat: any;
|
chat: any;
|
||||||
|
selectedContact: any;
|
||||||
sidebarFolded: boolean;
|
sidebarFolded: boolean;
|
||||||
user: any;
|
user: any;
|
||||||
view: string;
|
|
||||||
|
|
||||||
@ViewChild(FusePerfectScrollbarDirective)
|
|
||||||
set fusePerfectScrollbarDirective(content: FusePerfectScrollbarDirective)
|
|
||||||
{
|
|
||||||
this._fusePerfectScrollbarDirective = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewChild('replyForm')
|
@ViewChild('replyForm')
|
||||||
set replyForm(content: NgForm)
|
set replyForm(content: NgForm)
|
||||||
|
@ -42,8 +35,11 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
this._replyInput = content;
|
this._replyInput = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewChildren(FusePerfectScrollbarDirective)
|
||||||
|
private _fusePerfectScrollbarDirectives: QueryList<FusePerfectScrollbarDirective>;
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
private _fusePerfectScrollbarDirective: FusePerfectScrollbarDirective;
|
private _chatViewScrollbar: FusePerfectScrollbarDirective;
|
||||||
private _replyForm: NgForm;
|
private _replyForm: NgForm;
|
||||||
private _replyInput: ElementRef;
|
private _replyInput: ElementRef;
|
||||||
private _unsubscribeAll: Subject<any>;
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
@ -62,9 +58,8 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Set the defaults
|
// Set the defaults
|
||||||
this.contact = null;
|
this.selectedContact = null;
|
||||||
this.sidebarFolded = true;
|
this.sidebarFolded = true;
|
||||||
this.view = 'contacts';
|
|
||||||
|
|
||||||
// Set the private defaults
|
// Set the private defaults
|
||||||
this._unsubscribeAll = new Subject();
|
this._unsubscribeAll = new Subject();
|
||||||
|
@ -94,6 +89,16 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After view init
|
||||||
|
*/
|
||||||
|
ngAfterViewInit(): void
|
||||||
|
{
|
||||||
|
this._chatViewScrollbar = this._fusePerfectScrollbarDirectives.find((directive) => {
|
||||||
|
return directive.elementRef.nativeElement.id === 'messages';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On destroy
|
* On destroy
|
||||||
*/
|
*/
|
||||||
|
@ -122,12 +127,12 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
this._replyInput.nativeElement.focus();
|
this._replyInput.nativeElement.focus();
|
||||||
|
|
||||||
// Scroll to the bottom of the messages list
|
// Scroll to the bottom of the messages list
|
||||||
if ( this._fusePerfectScrollbarDirective )
|
if ( this._chatViewScrollbar )
|
||||||
{
|
{
|
||||||
this._fusePerfectScrollbarDirective.update();
|
this._chatViewScrollbar.update();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this._fusePerfectScrollbarDirective.scrollToBottom(0);
|
this._chatViewScrollbar.scrollToBottom(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -145,6 +150,22 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
this._fuseSidebarService.getSidebar('chatPanel').toggleFold();
|
this._fuseSidebarService.getSidebar('chatPanel').toggleFold();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Toggle sidebar opened status
|
||||||
*/
|
*/
|
||||||
|
@ -163,8 +184,8 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
shouldShowContactAvatar(message, i): boolean
|
shouldShowContactAvatar(message, i): boolean
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
message.who === this.contact.id &&
|
message.who === this.selectedContact.id &&
|
||||||
((this.chat.dialog[i + 1] && this.chat.dialog[i + 1].who !== this.contact.id) || !this.chat.dialog[i + 1])
|
((this.chat.dialog[i + 1] && this.chat.dialog[i + 1].who !== this.selectedContact.id) || !this.chat.dialog[i + 1])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,11 +220,11 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
*/
|
*/
|
||||||
goToChat(contact): void
|
goToChat(contact): void
|
||||||
{
|
{
|
||||||
// Change the view
|
// Unfold the sidebar temporarily
|
||||||
this.view = 'chat';
|
this.unfoldSidebarTemporarily();
|
||||||
|
|
||||||
// Set the current contact
|
// Set the selected contact
|
||||||
this.contact = contact;
|
this.selectedContact = contact;
|
||||||
|
|
||||||
// Load the chat
|
// Load the chat
|
||||||
this._chatPanelService.getChat(contact.id).then((chat) => {
|
this._chatPanelService.getChat(contact.id).then((chat) => {
|
||||||
|
@ -216,21 +237,6 @@ export class ChatPanelComponent implements OnInit, OnDestroy
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Go to contact view
|
|
||||||
*/
|
|
||||||
goToContacts(): void
|
|
||||||
{
|
|
||||||
// Change the view
|
|
||||||
this.view = 'contacts';
|
|
||||||
|
|
||||||
// Set the current contact as null
|
|
||||||
this.contact = null;
|
|
||||||
|
|
||||||
// Clear the chat data
|
|
||||||
this.chat = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reply
|
* Reply
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatRippleModule, MatTabsModule } from '@angular/material';
|
import { MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatRippleModule, MatTabsModule, MatTooltipModule } from '@angular/material';
|
||||||
|
|
||||||
import { FuseSharedModule } from '@fuse/shared.module';
|
import { FuseSharedModule } from '@fuse/shared.module';
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import { ChatPanelService } from 'app/layout/components/chat-panel/chat-panel.se
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatListModule,
|
MatListModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
|
MatTooltipModule,
|
||||||
MatRippleModule,
|
MatRippleModule,
|
||||||
|
|
||||||
FuseSharedModule
|
FuseSharedModule
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
<!-- CHAT PANEL -->
|
<!-- CHAT PANEL -->
|
||||||
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
||||||
[folded]="true" [foldedWidth]="70"
|
[folded]="true" [foldedWidth]="70" [foldedAutoTriggerOnHover]="false"
|
||||||
lockedOpen="gt-md">
|
lockedOpen="gt-md">
|
||||||
<chat-panel></chat-panel>
|
<chat-panel></chat-panel>
|
||||||
</fuse-sidebar>
|
</fuse-sidebar>
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
<!-- CHAT PANEL -->
|
<!-- CHAT PANEL -->
|
||||||
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
||||||
[folded]="true" [foldedWidth]="70"
|
[folded]="true" [foldedWidth]="70" [foldedAutoTriggerOnHover]="false"
|
||||||
lockedOpen="gt-md">
|
lockedOpen="gt-md">
|
||||||
<chat-panel></chat-panel>
|
<chat-panel></chat-panel>
|
||||||
</fuse-sidebar>
|
</fuse-sidebar>
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
<!-- CHAT PANEL -->
|
<!-- CHAT PANEL -->
|
||||||
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
||||||
[folded]="true" [foldedWidth]="70"
|
[folded]="true" [foldedWidth]="70" [foldedAutoTriggerOnHover]="false"
|
||||||
lockedOpen="gt-md">
|
lockedOpen="gt-md">
|
||||||
<chat-panel></chat-panel>
|
<chat-panel></chat-panel>
|
||||||
</fuse-sidebar>
|
</fuse-sidebar>
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
<!-- CHAT PANEL -->
|
<!-- CHAT PANEL -->
|
||||||
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
<fuse-sidebar class="chat-panel" name="chatPanel" position="right"
|
||||||
[folded]="true" [foldedWidth]="70"
|
[folded]="true" [foldedWidth]="70" [foldedAutoTriggerOnHover]="false"
|
||||||
lockedOpen="gt-md">
|
lockedOpen="gt-md">
|
||||||
<chat-panel></chat-panel>
|
<chat-panel></chat-panel>
|
||||||
</fuse-sidebar>
|
</fuse-sidebar>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user