Skip to content
This repository has been archived by the owner on May 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #136 from rpaschoal/2.0.5
Browse files Browse the repository at this point in the history
Merge 2.0.5 into Master
  • Loading branch information
rpaschoal authored Sep 2, 2019
2 parents 4586f79 + ecbca8a commit 145fcb0
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 46 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
dist: trusty
language: node_js
node_js:
- "10"

before_install:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
Expand All @@ -10,7 +10,7 @@ before_script:
- npm install
- cd src
- npm link
- npm install -g angular-cli
- npm install -g @angular/cli
- npm install -g karma
- npm install
script:
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ __Required Settings__

__Additional Settings__
* [title]{string}: The title to be displayed on the friends list. Default is "Friends".
* [isDisabled]{boolean}: Indicates if ng-chat should be hidden. This stops poll requests to the friends list. Default is false.
* [isCollapsed]{boolean}: If set to true the friends list will be rendered as collapsed by default. Default is false.
* [pollFriendsList]{boolean}: If set to true the module will do a long poll on the "adapter.listFriends" method to keep the friends list updated. Default is false.
* [pollingInterval]{number}: Configures the long poll interval in milliseconds. Default is 5000.
Expand All @@ -96,6 +97,7 @@ __Additional Settings__
* [showMessageDate]{boolean}: Shows the date in which a message was sent. Default is true.
* [messageDatePipeFormat]{string}: The format for the pipe that is used when rendering the date in which a message was sent. Default is "short".
* [groupAdapter]{IChatGroupAdapter}: A group adapter implementation to enable group chat.
* [isViewportOnMobileEnabled]{boolean}: Allow ng-chat to render and be displayed on mobile devices. Default is false.

__Localization__
* [messagePlaceholder]{string}: The placeholder that is displayed in the text input on each chat window. Default is "Type a message".
Expand Down
2 changes: 1 addition & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"assets": [
"demo/offline_bot/src/assets"
],
"tsConfig": "demo/offline_bot/src/../../../tsconfig.json",
"tsConfig": "demo/offline_bot/src/../../../tsconfig.json"
}
},
"lint": {
Expand Down
9 changes: 5 additions & 4 deletions demo/offline_bot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@
"@angular/platform-browser-dynamic": "^7.0.3",
"@angular/router": "^7.0.3",
"core-js": "^2.5.7",
"rxjs": "^6.3.3",
"zone.js": "^0.8.26",
"ng-chat": "^2.0.4"
"ng-chat": "^2.0.5",
"rxjs": "^6.5.2",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular-devkit/build-angular": "0.13.4",
"@angular/cli": "^7.0.4",
"@angular/compiler-cli": "^7.0.3",
"@angular/language-service": "^7.0.3",
Expand All @@ -45,6 +46,6 @@
"protractor": "~5.4.1",
"ts-node": "~7.0.1",
"tslint": "~5.11.0",
"typescript": "~3.1.6"
"typescript": "~3.2.4"
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"dependencies": {},
"devDependencies": {
"@angular-devkit/build-angular": "~0.10.0",
"@angular-devkit/build-angular": "^0.13.4",
"@angular/cli": "^7.0.5",
"@angular/common": "^7.0.3",
"@angular/compiler": "^7.0.3",
Expand Down Expand Up @@ -82,7 +82,7 @@
"tslint": "^5.11.0",
"tslint-config-valorsoft": "^2.2.1",
"typedoc": "^0.13.0",
"typescript": "~3.1.6",
"typescript": "~3.2.4",
"wallaby-webpack": "^3.9.13",
"webdriver-manager": "^12.1.0",
"zone.js": "^0.8.26"
Expand Down
29 changes: 22 additions & 7 deletions src/ng-chat/assets/ng-chat.component.default.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
height:360px;
border-width: 1px;
border-style: solid;
margin-right:20px;
margin-right: 20px;
box-shadow: 0 4px 8px rgba(0,0,0,.25);
border-bottom:0;
}
Expand Down Expand Up @@ -212,15 +212,15 @@
}
.ng-chat-window
{
right:260px;
height:360px;
z-index:999;
bottom:0;
right: 260px;
height: 360px;
z-index: 999;
bottom: 0;
width: 300px;
position: fixed;
width:300px;
border-width: 1px;
border-style: solid;
border-bottom:0;
border-bottom: 0;
box-shadow: 0 4px 8px rgba(0,0,0,.25);
}
.ng-chat-window-collapsed
Expand Down Expand Up @@ -417,3 +417,18 @@
float: right;
margin-right: 5px;
}

/* Mobile viewport only */
@media only screen and (max-width: 581px) {
#ng-chat-people
{
width: 300px;
height: 360px;
margin-right: 0;
}

.ng-chat-window
{
position: initial;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,9 @@
display: block;
}

/* Mobile viewport only */
@media only screen and (max-width: 581px) {
.ng-chat-options-content {
right: 0;
}
}
8 changes: 4 additions & 4 deletions src/ng-chat/ng-chat.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<link *ngIf="customTheme" rel="stylesheet" [href]='sanitizer.bypassSecurityTrustResourceUrl(customTheme)'>
<link *ngIf="customTheme" rel="stylesheet" [href]='customTheme | sanitize'>

<div id="ng-chat" *ngIf="isBootstrapped && !unsupportedViewport" [ngClass]="theme">
<div id="ng-chat" *ngIf="!isDisabled && isBootstrapped && !unsupportedViewport" [ngClass]="theme">
<div *ngIf="!hideFriendsList" id="ng-chat-people" [ngClass]="{'primary-outline-color': true, 'primary-background': true, 'ng-chat-people-collapsed': isCollapsed}">
<a href="javascript:void(0);" class="ng-chat-title secondary-background shadowed" (click)="onChatTitleClicked($event)">
<span>
Expand Down Expand Up @@ -28,7 +28,7 @@
<div *ngIf="!user.avatar" class="icon-wrapper">
<i class="user-icon"></i>
</div>
<img *ngIf="user.avatar" alt="" class="avatar" height="30" width="30" [src]="sanitizer.bypassSecurityTrustResourceUrl(user.avatar)"/>
<img *ngIf="user.avatar" alt="" class="avatar" height="30" width="30" [src]="user.avatar | sanitize"/>
<strong title="{{user.displayName}}">{{user.displayName}}</strong>
<span [ngClass]="{'ng-chat-participant-status': true, 'online': user.status == ChatParticipantStatus.Online, 'busy': user.status == ChatParticipantStatus.Busy, 'away': user.status == ChatParticipantStatus.Away, 'offline': user.status == ChatParticipantStatus.Offline}" title="{{getStatusTitle(user.status)}}"></span>
<span *ngIf="unreadMessagesTotalByParticipant(user).length > 0" class="ng-chat-unread-messages-count unread-messages-counter-container primary-text">{{unreadMessagesTotalByParticipant(user)}}</span>
Expand Down Expand Up @@ -74,7 +74,7 @@
<div *ngIf="!getChatWindowAvatar(window.participant, message)" class="icon-wrapper">
<i class="user-icon"></i>
</div>
<img *ngIf="getChatWindowAvatar(window.participant, message)" alt="" class="avatar" height="30" width="30" [src]="sanitizer.bypassSecurityTrustResourceUrl(getChatWindowAvatar(window.participant, message))" />
<img *ngIf="getChatWindowAvatar(window.participant, message)" alt="" class="avatar" height="30" width="30" [src]="getChatWindowAvatar(window.participant, message) | sanitize" />
<span *ngIf="window.participant.participantType == ChatParticipantType.Group" class="ng-chat-participant-name">{{window.participant | groupMessageDisplayName:message}}</span>
</ng-container>
<ng-container [ngSwitch]="message.type">
Expand Down
75 changes: 55 additions & 20 deletions src/ng-chat/ng-chat.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Component, Input, OnInit, ViewChildren, ViewChild, HostListener, Output, EventEmitter, ElementRef, ViewEncapsulation } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser';

import { ChatAdapter } from './core/chat-adapter';
import { IChatGroupAdapter } from './core/chat-group-adapter';
Expand Down Expand Up @@ -40,13 +39,34 @@ import { Observable } from 'rxjs';
})

export class NgChat implements OnInit, IChatController {
constructor(public sanitizer: DomSanitizer, private _httpClient: HttpClient) { }
constructor(private _httpClient: HttpClient) { }

// Exposes enums for the ng-template
public ChatParticipantType = ChatParticipantType;
public ChatParticipantStatus = ChatParticipantStatus;
public MessageType = MessageType;

private _isDisabled: boolean = false;

get isDisabled(): boolean {
return this._isDisabled;
}

@Input()
set isDisabled(value: boolean) {
this._isDisabled = value;

if (value)
{
// To address issue https://github.com/rpaschoal/ng-chat/issues/120
window.clearInterval(this.pollingIntervalWindowInstance)
}
else
{
this.activateFriendListFetch();
}
}

@Input()
public adapter: ChatAdapter;

Expand Down Expand Up @@ -133,7 +153,10 @@ export class NgChat implements OnInit, IChatController {

@Input()
public showMessageDate: boolean = true;


@Input()
public isViewportOnMobileEnabled: boolean = false;

@Output()
public onParticipantClicked: EventEmitter<IChatParticipant> = new EventEmitter<IChatParticipant>();

Expand Down Expand Up @@ -172,6 +195,8 @@ export class NgChat implements OnInit, IChatController {

protected selectedUsersFromFriendsList: User[] = [];

private pollingIntervalWindowInstance: number;

public defaultWindowOptions(currentWindow: Window): IChatOption[]
{
if (this.groupAdapter && currentWindow.participant.participantType == ChatParticipantType.User)
Expand Down Expand Up @@ -256,8 +281,8 @@ export class NgChat implements OnInit, IChatController {

this.updateWindowsState(this.windows);

// Viewport should have space for at least one chat window.
this.unsupportedViewport = this.hideFriendsListOnUnsupportedViewport && maxSupportedOpenedWindows < 1;
// Viewport should have space for at least one chat window but should show in mobile if option is enabled.
this.unsupportedViewport = this.isViewportOnMobileEnabled? false : this.hideFriendsListOnUnsupportedViewport && maxSupportedOpenedWindows < 1;
}

// Initializes the chat plugin and the messaging adapter
Expand All @@ -279,17 +304,7 @@ export class NgChat implements OnInit, IChatController {
this.adapter.messageReceivedHandler = (participant, msg) => this.onMessageReceived(participant, msg);
this.adapter.friendsListChangedHandler = (participantsResponse) => this.onFriendsListChanged(participantsResponse);

// Loading current users list
if (this.pollFriendsList){
// Setting a long poll interval to update the friends list
this.fetchFriendsList(true);
setInterval(() => this.fetchFriendsList(false), this.pollingInterval);
}
else
{
// Since polling was disabled, a friends list update mechanism will have to be implemented in the ChatAdapter.
this.fetchFriendsList(true);
}
this.activateFriendListFetch();

this.bufferAudioFile();

Expand All @@ -300,6 +315,8 @@ export class NgChat implements OnInit, IChatController {
this.fileUploadAdapter = new DefaultFileUploadAdapter(this.fileUploadUrl, this._httpClient);
}

this.NormalizeWindows();

this.isBootstrapped = true;
}
catch(ex)
Expand All @@ -325,6 +342,23 @@ export class NgChat implements OnInit, IChatController {
}
}

private activateFriendListFetch(): void {
if (this.adapter)
{
// Loading current users list
if (this.pollFriendsList){
// Setting a long poll interval to update the friends list
this.fetchFriendsList(true);
this.pollingIntervalWindowInstance = window.setInterval(() => this.fetchFriendsList(false), this.pollingInterval);
}
else
{
// Since polling was disabled, a friends list update mechanism will have to be implemented in the ChatAdapter.
this.fetchFriendsList(true);
}
}
}

// Initializes browser notifications
private async initializeBrowserNotifications()
{
Expand Down Expand Up @@ -512,10 +546,11 @@ export class NgChat implements OnInit, IChatController {

this.windows.unshift(newChatWindow);

// Is there enough space left in the view port ?
if (this.windows.length * this.windowSizeFactor >= this.viewPortTotalArea - (!this.hideFriendsList ? this.friendsListWidth : 0))
{
this.windows.pop();
// Is there enough space left in the view port ? but should be displayed in mobile if option is enabled
if (!this.isViewportOnMobileEnabled) {
if (this.windows.length * this.windowSizeFactor >= this.viewPortTotalArea - (!this.hideFriendsList ? this.friendsListWidth : 0)) {
this.windows.pop();
}
}

this.updateWindowsState(this.windows);
Expand Down
3 changes: 2 additions & 1 deletion src/ng-chat/ng-chat.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { HttpClientModule } from '@angular/common/http';
import { NgChat } from './ng-chat.component';
import { EmojifyPipe } from './pipes/emojify.pipe';
import { LinkfyPipe } from './pipes/linkfy.pipe';
import { SanitizePipe } from './pipes/sanitize.pipe';
import { GroupMessageDisplayNamePipe } from './pipes/group-message-display-name.pipe';
import { NgChatOptionsComponent } from './components/ng-chat-options/ng-chat-options.component';

@NgModule({
imports: [CommonModule, FormsModule, HttpClientModule],
declarations: [NgChat, EmojifyPipe, LinkfyPipe, GroupMessageDisplayNamePipe, NgChatOptionsComponent],
declarations: [NgChat, EmojifyPipe, LinkfyPipe, SanitizePipe, GroupMessageDisplayNamePipe, NgChatOptionsComponent],
exports: [NgChat]
})
export class NgChatModule {
Expand Down
14 changes: 14 additions & 0 deletions src/ng-chat/pipes/sanitize.pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

/*
* Sanitizes an URL resource
*/
@Pipe({name: 'sanitize'})
export class SanitizePipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}

transform(url: string): SafeResourceUrl {
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
}
}
6 changes: 3 additions & 3 deletions src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng-chat",
"version": "2.0.4",
"version": "2.0.5",
"peerDependencies": {
"@angular/common": "*",
"@angular/core": "*",
Expand All @@ -13,13 +13,13 @@
"@angular/forms": "^7.0.3",
"@angular/platform-browser": "^7.0.3",
"zone.js": "^0.8.26",
"rxjs": "^6.3.3",
"rxjs": "^6.5.2",
"@angular/compiler": "^7.0.3",
"@angular/compiler-cli": "^7.0.3",
"gulp": "~4.0.0",
"gulp-inline-ng2-template": "^5.0.1",
"rollup": "^0.67.0",
"typescript": "~3.1.6",
"typescript": "~3.2.4",
"uglify-js": "^3.4.9",
"ng-packagr": "^4.4.0",
"tsickle": "^0.33.1"
Expand Down
8 changes: 6 additions & 2 deletions src/spec/ng-chat.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ let subject: any = null;

describe('NgChat', () => {
beforeEach(() => {
subject = new NgChat(null, null); // HttpClient related methods are tested elsewhere
subject = new NgChat(null); // HttpClient related methods are tested elsewhere
subject.userId = 123;
subject.adapter = new MockableAdapter();
subject.groupAdapter = new MockableGroupAdapter();
Expand Down Expand Up @@ -97,7 +97,11 @@ describe('NgChat', () => {
it('Persistent windows state must be enabled by default', () => {
expect(subject.persistWindowsState).toBeTruthy();
});


it('Is viewport mobile case state must be disabled by default', () => {
expect(subject.isViewportOnMobileEnabled).toBeFalsy();
});

it('isCollapsed must be disabled by default', () => {
expect(subject.isCollapsed).toBeFalsy();
});
Expand Down

0 comments on commit 145fcb0

Please sign in to comment.