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 #125 from rpaschoal/2.0.4
Browse files Browse the repository at this point in the history
Merge from 2.0.4
  • Loading branch information
rpaschoal authored May 10, 2019
2 parents e62416a + 75cae89 commit 4586f79
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 42 deletions.
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.7",
"rxjs": "^6.3.3",
"zone.js": "^0.8.26",
"ng-chat": "^2.0.3"
"ng-chat": "^2.0.4"
},
"devDependencies": {
"@angular/cli": "^7.0.4",
Expand Down
11 changes: 8 additions & 3 deletions src/ng-chat/ng-chat.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,16 @@

<!-- File Upload -->
<ng-container *ngIf="fileUploadAdapter">
<a *ngIf="!isUploadingFile" class="btn-add-file" (click)="triggerNativeFileUpload()">
<a *ngIf="!isUploadingFile(window)" class="btn-add-file" (click)="triggerNativeFileUpload(window)">
<i class="upload-icon"></i>
</a>
<input type="file" #nativeFileInput style="display: none;" (change)="onFileChosen(window)" />
<div *ngIf="isUploadingFile" class="loader"></div>
<input
type="file"
#nativeFileInput
style="display: none;"
[attr.id]="getUniqueFileUploadInstanceId(window)"
(change)="onFileChosen(window)" />
<div *ngIf="isUploadingFile(window)" class="loader"></div>
</ng-container>
</div>
</ng-container>
Expand Down
88 changes: 64 additions & 24 deletions src/ng-chat/ng-chat.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export class NgChat implements OnInit, IChatController {
public unsupportedViewport: boolean = false;

// File upload state
public isUploadingFile = false;
public fileUploadersInUse: string[] = []; // Id bucket of uploaders in use
public fileUploadAdapter: IFileUploadAdapter;

windows: Window[] = [];
Expand All @@ -231,7 +231,7 @@ export class NgChat implements OnInit, IChatController {

@ViewChildren('chatWindowInput') chatWindowInputs: any;

@ViewChild('nativeFileInput') nativeFileInput: ElementRef;
@ViewChildren('nativeFileInput') nativeFileInputs: ElementRef[];

ngOnInit() {
this.bootstrapChat();
Expand Down Expand Up @@ -891,41 +891,81 @@ export class NgChat implements OnInit, IChatController {
}
}

// Generates a unique file uploader id for each participant
getUniqueFileUploadInstanceId(window: Window): string
{
if (window && window.participant)
{
return `ng-chat-file-upload-${window.participant.id}`;
}

return 'ng-chat-file-upload';
}

// Triggers native file upload for file selection from the user
triggerNativeFileUpload(): void
triggerNativeFileUpload(window: Window): void
{
if (window)
{
const fileUploadInstanceId = this.getUniqueFileUploadInstanceId(window);
const uploadElementRef = this.nativeFileInputs.filter(x => x.nativeElement.id === fileUploadInstanceId)[0];

if (uploadElementRef)
uploadElementRef.nativeElement.click();
}
}

private clearInUseFileUploader(fileUploadInstanceId: string): void
{
const uploaderInstanceIdIndex = this.fileUploadersInUse.indexOf(fileUploadInstanceId);

if (uploaderInstanceIdIndex > -1) {
this.fileUploadersInUse.splice(uploaderInstanceIdIndex, 1);
}
}

isUploadingFile(window: Window): boolean
{
this.nativeFileInput.nativeElement.click();
const fileUploadInstanceId = this.getUniqueFileUploadInstanceId(window);

return this.fileUploadersInUse.indexOf(fileUploadInstanceId) > -1;
}

// Handles file selection and uploads the selected file using the file upload adapter
onFileChosen(window: Window): void {
const file: File = this.nativeFileInput.nativeElement.files[0];
const fileUploadInstanceId = this.getUniqueFileUploadInstanceId(window);
const uploadElementRef = this.nativeFileInputs.filter(x => x.nativeElement.id === fileUploadInstanceId)[0];

this.isUploadingFile = true;
if (uploadElementRef)
{
const file: File = uploadElementRef.nativeElement.files[0];

this.fileUploadAdapter.uploadFile(file, window.participant.id)
.subscribe(fileMessage => {
this.isUploadingFile = false;
this.fileUploadersInUse.push(fileUploadInstanceId);

fileMessage.fromId = this.userId;
this.fileUploadAdapter.uploadFile(file, window.participant.id)
.subscribe(fileMessage => {
this.clearInUseFileUploader(fileUploadInstanceId);

// Push file message to current user window
window.messages.push(fileMessage);

this.adapter.sendMessage(fileMessage);

this.scrollChatWindow(window, ScrollDirection.Bottom);
fileMessage.fromId = this.userId;

// Resets the file upload element
this.nativeFileInput.nativeElement.value = '';
}, (error) => {
this.isUploadingFile = false;
// Push file message to current user window
window.messages.push(fileMessage);

this.adapter.sendMessage(fileMessage);

this.scrollChatWindow(window, ScrollDirection.Bottom);

// Resets the file upload element
this.nativeFileInput.nativeElement.value = '';
// Resets the file upload element
uploadElementRef.nativeElement.value = '';
}, (error) => {
this.clearInUseFileUploader(fileUploadInstanceId);

// TODO: Invoke a file upload adapter error here
});
// Resets the file upload element
uploadElementRef.nativeElement.value = '';

// TODO: Invoke a file upload adapter error here
});
}
}

onFriendsListCheckboxChange(selectedUser: User, isChecked: boolean): void
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": "2.0.3",
"version": "2.0.4",
"peerDependencies": {
"@angular/common": "*",
"@angular/core": "*",
Expand Down
39 changes: 26 additions & 13 deletions src/spec/ng-chat.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1545,34 +1545,46 @@ describe('NgChat', () => {
expect(spy).not.toHaveBeenCalled();
});

it('Exercise for "onFileChosen" event', () => {
let mockedFileMessageServerResponse = new FileMessage();
it('Should filter by file instance id and upload file when a file upload "onFileChosen" event is triggered', () => {
const mockedFileMessageServerResponse = new FileMessage();

const chattingTo = new User();
chattingTo.id = 88;

const chatWindow = new Window(chattingTo, false, false);

spyOn(MockableFileUploadAdapter.prototype, 'uploadFile').and.callFake(() => {
// At this stage the 'isUploadingFile' should be true
expect(subject.isUploadingFile).toBeTruthy();
expect(subject.isUploadingFile(chatWindow)).toBeTruthy();

return of(mockedFileMessageServerResponse);
});
spyOn(MockableAdapter.prototype, 'sendMessage');
let scrollSpy = spyOn(subject, 'scrollChatWindow');

let chattingTo = new User();
chattingTo.id = 88;

let chatWindow = new Window(chattingTo, false, false);
spyOn(MockableAdapter.prototype, 'sendMessage');
const scrollSpy = spyOn(subject, 'scrollChatWindow');

let fakeFile = new File([''], 'filename', { type: 'text/html' });
const fakeFile = new File([''], 'filename', { type: 'text/html' });

let fakeFileElement = {
const fakeFileElement = {
nativeElement:
{
id: `ng-chat-file-upload-${chattingTo.id}`,
value: 'test',
files: [fakeFile]
}
}

subject.nativeFileInput = fakeFileElement;
// Should be filtered and ignored
const anotherFakeFileElement = {
nativeElement:
{
id: `ng-chat-file-upload-${123}`,
value: 'test',
files: []
}
}

subject.nativeFileInputs = [anotherFakeFileElement, fakeFileElement];
subject.fileUploadAdapter = new MockableFileUploadAdapter();

subject.onFileChosen(chatWindow);
Expand All @@ -1585,7 +1597,8 @@ describe('NgChat', () => {
expect(scrollSpy).toHaveBeenCalledTimes(1);
expect(scrollSpy.calls.mostRecent().args[1]).toBe(ScrollDirection.Bottom);
expect(fakeFileElement.nativeElement.value).toBe('');
expect(subject.isUploadingFile).toBeFalsy();
expect(anotherFakeFileElement.nativeElement.value).toBe('test');
expect(subject.isUploadingFile(chatWindow)).toBeFalsy();
});

it('Assert message type must default to text when no message type is defined in a message instance', () => {
Expand Down

0 comments on commit 4586f79

Please sign in to comment.