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 #53 from rpaschoal/1.0.11
Browse files Browse the repository at this point in the history
Merge from 1.0.11
  • Loading branch information
rpaschoal authored Jun 4, 2018
2 parents 7aaf7a1 + e0feacf commit 4390713
Show file tree
Hide file tree
Showing 7 changed files with 320 additions and 27 deletions.
37 changes: 22 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,32 @@ export class AppComponent {
```

__Required Settings__
* [adapter]{string}: This will point to your adapter implementation ('MyAdapter' in the example above).
* [userId]{any}: The unique id of the user that will be using the chat instance.
* [adapter]<string>: This will point to your adapter implementation ('MyAdapter' in the example above).
* [userId]<any>: The unique id of the user that will be using the chat instance.

__Additional Settings__
* [title]{string}: The title to be displayed on the friends list. Default is "Friends".
* [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.
* [historyEnabled]{boolean}: Defines whether the component should call the "getMessageHistory" from the chat-adapter. Default is true.
* [emojisEnabled]{boolean}: Enables emoji parsing on the messages. Default is true.
* [linkfyEnabled]{boolean}: Transforms links within the messages to valid HTML links. Default is true.
* [audioEnabled]{boolean}: Enables audio notifications on received messages. Default is true.
* [audioSource]{string}: WAV source of the audio notification. Default is a RAW github WAV content from ng-chat repository.
* [persistWindowsState]{boolean}: Saves the state of current open windows on the local storage. Default is true.
* [title]<string>: The title to be displayed on the friends list. Default is "Friends".
* [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.
* [historyEnabled]<boolean>: Defines whether the component should call the "getMessageHistory" from the chat-adapter. Default is true.
* [emojisEnabled]<boolean>: Enables emoji parsing on the messages. Default is true.
* [linkfyEnabled]<boolean>: Transforms links within the messages to valid HTML links. Default is true.
* [audioEnabled]<boolean>: Enables audio notifications on received messages. Default is true.
* [audioSource]<string>: WAV source of the audio notification. Default is a RAW github WAV content from ng-chat repository.
* [persistWindowsState]<boolean>: Saves the state of current open windows on the local storage. Default is true.
* [browserNotificationsEnabled]<boolean>: Enables browser notifications on received messages. Default is true.
* [browserNotificationIconSource]<string>: Source URL of the icon displayed on the browser notification. Default is a RAW github PNG content from ng-chat repository.

__Localization__
* [messagePlaceholder]{string}: The placeholder that is displayed in the text input on each chat window. Default is "Type a message".
* [searchPlaceholder]{string}: The placeholder that is displayed in the search input on the friends list. Default is "Search".
* [localization]{Localization}: Contract defining all text that is rendered by this component. Supply your own object for full text localization/customization. Supplying this setting will override all other localization settings.
* [messagePlaceholder]<string>: The placeholder that is displayed in the text input on each chat window. Default is "Type a message".
* [searchPlaceholder]<string>: The placeholder that is displayed in the search input on the friends list. Default is "Search".
* [localization]<Localization>: Contract defining all text that is rendered by this component. Supply your own object for full text localization/customization. Supplying this setting will override all other localization settings.

__Events__
* (onUserClicked)<User>: Event emitted every time a user is clicked on the chat window and a new chat window is opened.
* (onUserChatOpened)<User>: Event emitted every time a chat window is opened, regardless if it was due to a user click on the friends list or via new message received.
* (onUserChatClosed)<User>: Event emitted every time a chat window is closed.

#### Implement your ChatAdapter:

Expand Down
2 changes: 1 addition & 1 deletion demo/aspnetcore_signalr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"bootstrap": "^3.3.7",
"core-js": "^2.4.1",
"jquery": "3.2.1",
"ng-chat": "^1.0.10",
"ng-chat": "^1.0.11",
"ng2-loading-bar": "0.0.6",
"reflect-metadata": "^0.1.10",
"rxjs": "5.4.2",
Expand Down
2 changes: 1 addition & 1 deletion demo/offline_bot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"core-js": "^2.5.3",
"rxjs": "^5.5.6",
"zone.js": "^0.8.20",
"ng-chat": "^1.0.10"
"ng-chat": "^1.0.11"
},
"devDependencies": {
"@angular/cli": "^1.6.4",
Expand Down
2 changes: 1 addition & 1 deletion src/ng-chat/ng-chat.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</a>
<input id="ng-chat-search_friend" type="search" [placeholder]="localization.searchPlaceholder" [(ngModel)]="searchInput"/>
<ul id="ng-chat-users" *ngIf="!isCollapsed">
<li *ngFor="let user of filteredUsers" (click)="openChatWindow(user, true)">
<li *ngFor="let user of filteredUsers" (click)="openChatWindow(user, true, true)">
<div *ngIf="!user.avatar" class="icon-wrapper">
<i class="user-icon"></i>
</div>
Expand Down
77 changes: 69 additions & 8 deletions src/ng-chat/ng-chat.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input, OnInit, ViewChildren, HostListener } from '@angular/core';
import { Component, Input, OnInit, ViewChildren, HostListener, Output, EventEmitter } from '@angular/core';
import { ChatAdapter } from './core/chat-adapter';
import { User } from "./core/user";
import { Message } from "./core/message";
Expand Down Expand Up @@ -65,6 +65,26 @@ export class NgChat implements OnInit {
@Input()
public searchPlaceholder: string = "Search";

@Input()
public browserNotificationsEnabled: boolean = true;

@Input() // TODO: This might need a better content strategy
public browserNotificationIconSource: string = 'https://raw.githubusercontent.com/rpaschoal/ng-chat/master/src/ng-chat/assets/notification.png';

@Input()
public localization: Localization;

@Output()
public onUserClicked: EventEmitter<User> = new EventEmitter<User>();

@Output()
public onUserChatOpened: EventEmitter<User> = new EventEmitter<User>();

@Output()
public onUserChatClosed: EventEmitter<User> = new EventEmitter<User>();

private browserNotificationsBootstrapped: boolean = false;

// Don't want to add this as a setting to simplify usage. Previous placeholder and title settings available to be used, or use full Localization object.
private statusDescription: StatusDescription = {
online: 'Online',
Expand All @@ -73,9 +93,6 @@ export class NgChat implements OnInit {
offline: 'Offline'
};

@Input()
public localization: Localization;

private audioFile: HTMLAudioElement;

public searchInput: string = '';
Expand Down Expand Up @@ -144,6 +161,7 @@ export class NgChat implements OnInit {
this.viewPortTotalArea = window.innerWidth;

this.initializeDefaultText();
this.initializeBrowserNotifications();

// Binding event listeners
this.adapter.messageReceivedHandler = (user, msg) => this.onMessageReceived(user, msg);
Expand Down Expand Up @@ -178,6 +196,18 @@ export class NgChat implements OnInit {
}
}

// Initializes browser notifications
private async initializeBrowserNotifications()
{
if (this.browserNotificationsEnabled && ("Notification" in window))
{
if (await Notification.requestPermission())
{
this.browserNotificationsBootstrapped = true;
}
}
}

// Initializes default text
private initializeDefaultText() : void
{
Expand Down Expand Up @@ -209,7 +239,8 @@ export class NgChat implements OnInit {
// Updates the friends list via the event handler
private onFriendsListChanged(users: User[]): void
{
if (users){
if (users)
{
this.users = users;
}
}
Expand All @@ -228,18 +259,24 @@ export class NgChat implements OnInit {
}

this.emitMessageSound(chatWindow[0]);
this.emitBrowserNotification(chatWindow[0]);
}
}

// Opens a new chat whindow. Takes care of available viewport
// Returns => [Window: Window object reference, boolean: Indicates if this window is a new chat window]
private openChatWindow(user: User, focusOnNewWindow: boolean = false): [Window, boolean]
private openChatWindow(user: User, focusOnNewWindow: boolean = false, invokedByUserClick: boolean = false): [Window, boolean]
{
// Is this window opened?
let openedWindow = this.windows.find(x => x.chattingTo.id == user.id);

if (!openedWindow)
{
if (invokedByUserClick)
{
this.onUserClicked.emit(user);
}

let newChatWindow: Window = {
chattingTo: user,
messages: [],
Expand All @@ -263,14 +300,19 @@ export class NgChat implements OnInit {
this.windows.unshift(newChatWindow);

// Is there enough space left in the view port ?
if (this.windows.length * this.windowSizeFactor >= this.viewPortTotalArea - this.friendsListWidth){
if (this.windows.length * this.windowSizeFactor >= this.viewPortTotalArea - this.friendsListWidth)
{
this.windows.pop();
}

this.updateWindowsState(this.windows);

if (focusOnNewWindow)
if (focusOnNewWindow)
{
this.focusOnWindow(newChatWindow);
}

this.onUserChatOpened.emit(user);

return [newChatWindow, true];
}
Expand Down Expand Up @@ -339,6 +381,23 @@ export class NgChat implements OnInit {
}
}

// Emits a browser notification
private emitBrowserNotification(window: Window): void
{
if (this.browserNotificationsBootstrapped && !window.hasFocus) {
let message = window.messages[window.messages.length - 1].message;

let notification = new Notification(`New message from ${window.chattingTo.displayName}`, {
'body': window.messages[window.messages.length - 1].message,
'icon': this.browserNotificationIconSource
});

setTimeout(() => {
notification.close();
}, message.length <= 50 ? 5000 : 7000); // More time to read longer messages
}
}

// Saves current windows state into local storage if persistence is enabled
private updateWindowsState(windows: Window[]): void
{
Expand Down Expand Up @@ -481,6 +540,8 @@ export class NgChat implements OnInit {
this.windows.splice(index, 1);

this.updateWindowsState(this.windows);

this.onUserChatClosed.emit(window.chattingTo);
}

// Toggle friends list visibility
Expand Down
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng-chat",
"version": "1.0.10",
"version": "1.0.11",
"peerDependencies": {
"@angular/common": "*",
"@angular/core": "*",
Expand Down
Loading

0 comments on commit 4390713

Please sign in to comment.