Added logic for fetching new messages
This commit is contained in:
parent
b236b87e5d
commit
e1520d5182
@ -5,6 +5,7 @@ import { ChatMessageViewModel } from "../viewmodel/ChatMessageViewModel";
|
|||||||
import { ChatModelHelper } from "./ChatModelHelper";
|
import { ChatModelHelper } from "./ChatModelHelper";
|
||||||
import log = require('loglevel');
|
import log = require('loglevel');
|
||||||
import { ObserverData } from "../observe/ObserverData";
|
import { ObserverData } from "../observe/ObserverData";
|
||||||
|
import { ActiveUserViewModel } from "../viewmodel/ActiveUserViewModel";
|
||||||
|
|
||||||
interface Params {
|
interface Params {
|
||||||
userName: string,
|
userName: string,
|
||||||
@ -44,10 +45,11 @@ export class ChatModel implements Subject<ChatMessageViewModel> {
|
|||||||
|
|
||||||
private storeUserMessages(username: string, messages: ChatMessageViewModel[], op: string) {
|
private storeUserMessages(username: string, messages: ChatMessageViewModel[], op: string) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case "clear": this._messagesMap.set(username, []);
|
case "clear": this._messagesMap.set(username, []); break;
|
||||||
case "page": this._messagesMap.set(username, messages.concat(this.getStoredUserMessages(username))); break;
|
case "page": this._messagesMap.set(username, messages.concat(this.getStoredUserMessages(username))); break;
|
||||||
// case "page": this._messagesMap.set(username, messages);
|
// case "page": this._messagesMap.set(username, messages);
|
||||||
case "new": this._messagesMap.set(username, this.getStoredUserMessages(username).concat(messages)); break;
|
case "new": this._messagesMap.set(username, this.getStoredUserMessages(username).concat(messages)); break;
|
||||||
|
case "update": this._messagesMap.set(username, this.getStoredUserMessages(username).concat(messages)); break;
|
||||||
default: new Error("Invalid option");
|
default: new Error("Invalid option");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +88,12 @@ export class ChatModel implements Subject<ChatMessageViewModel> {
|
|||||||
observer.update(od);
|
observer.update(od);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case "update": {
|
||||||
|
const od: ObserverData<ChatMessageViewModel> = { data: p.data, op: p.op }
|
||||||
|
for (const observer of this._observers) {
|
||||||
|
observer.update(od);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default: { log.error("error") }
|
default: { log.error("error") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,28 +108,31 @@ export class ChatModel implements Subject<ChatMessageViewModel> {
|
|||||||
this.notify({ userName: "", data: [], op: "clear" })
|
this.notify({ userName: "", data: [], op: "clear" })
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getMessages(contactName: string, passphrase: string, lastMessageTime: string | null, op: string): Promise<ChatMessageViewModel[]> {
|
public async getMessages(vm: ActiveUserViewModel, op: string): Promise<ChatMessageViewModel[]> {
|
||||||
if (this._messagePageMap.get(contactName) == null)
|
if (this._messagePageMap.get(vm.userName!) == null)
|
||||||
this._messagePageMap.set(contactName, 0);
|
this._messagePageMap.set(vm.userName!, 0);
|
||||||
|
|
||||||
const pageNumber = this._messagePageMap.get(contactName)
|
const pageNumber = this._messagePageMap.get(vm.userName!)
|
||||||
const cVMs = await this._chatModelHelper.getMessages(contactName, passphrase, pageNumber!, lastMessageTime, op);
|
const cVMs = await this._chatModelHelper.getMessages(vm.userName!, vm.passphrase, pageNumber!, vm.lastMessageTime!, op);
|
||||||
if (cVMs != null) {
|
if (cVMs != null) {
|
||||||
log.info('Subject: My state has just changed')
|
log.info('Subject: My state has just changed')
|
||||||
const existingMessages = this.getStoredUserMessages(contactName);
|
const existingMessages = this.getStoredUserMessages(vm.userName!);
|
||||||
log.debug('existing message:')
|
log.debug('existing message:')
|
||||||
log.debug(existingMessages);
|
log.debug(existingMessages);
|
||||||
log.debug('new messages:')
|
log.debug('new messages:')
|
||||||
log.debug(cVMs);
|
log.debug(cVMs);
|
||||||
this.storeUserMessages(contactName, cVMs, op);
|
this.storeUserMessages(vm.userName!, cVMs, op);
|
||||||
this.notify({ userName: contactName, data: cVMs, op: op });
|
this.notify({ userName: vm.userName!, data: cVMs, op: op });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.error('Messages were null');
|
log.error('Messages were null');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cVMs.length != 0) {
|
if (cVMs.length != 0 && op == "update") vm.lastMessageTime = cVMs[cVMs.length - 1].messageTime;
|
||||||
this._messagePageMap.set(contactName, this._messagePageMap.get(contactName)! + 1);
|
|
||||||
|
if (cVMs.length != 0 && op != "update") {
|
||||||
|
|
||||||
|
this._messagePageMap.set(vm.userName!, this._messagePageMap.get(vm.userName!)! + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cVMs;
|
return cVMs;
|
||||||
|
@ -18,17 +18,26 @@ export class ChatModelHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async getMessages(userName: string, passphrase: string, page: number | null, lastMessageTime: string | null, op: string): Promise<ChatMessageViewModel[]> {
|
public async getMessages(userName: string, passphrase: string, page: number | null, lastMessageTime: Date | null, op: string): Promise<ChatMessageViewModel[]> {
|
||||||
switch (lastMessageTime) {
|
switch (op) {
|
||||||
case null: {
|
case "page": {
|
||||||
const data: ChatMessageDTO[] = await this._getPaginatedMessagesAjax(userName, page!);
|
const data: ChatMessageDTO[] = await this._getPaginatedMessagesAjax(userName, page!);
|
||||||
const cVMs = Promise.all(data.map(vm => this._toChatMessageVMAsync(vm, passphrase)).reverse());
|
const cVMs = Promise.all(data.map(vm => this._toChatMessageVMAsync(vm, passphrase)).reverse());
|
||||||
return cVMs;
|
return cVMs;
|
||||||
}
|
}
|
||||||
default: {
|
case "new": {
|
||||||
|
const data: ChatMessageDTO[] = await this._getPaginatedMessagesAjax(userName, page!);
|
||||||
|
const cVMs = Promise.all(data.map(vm => this._toChatMessageVMAsync(vm, passphrase)).reverse());
|
||||||
|
return cVMs;
|
||||||
|
}
|
||||||
|
case "update": {
|
||||||
const data: ChatMessageDTO[] = await this._getNewMessagesAjax(userName, lastMessageTime!);
|
const data: ChatMessageDTO[] = await this._getNewMessagesAjax(userName, lastMessageTime!);
|
||||||
return data.map(vm => this._toChatMessageVM(vm, passphrase));
|
return data.map(vm => this._toChatMessageVM(vm, passphrase));
|
||||||
}
|
}
|
||||||
|
default: {
|
||||||
|
log.error("Invalid operation");
|
||||||
|
return Array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,17 +111,30 @@ export class ChatModelHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const data: Promise<any> = await response.json();
|
const data: Promise<any> = await response.json();
|
||||||
return data;
|
function func(data: any) {
|
||||||
|
const d1 = data.map((d: any) => {
|
||||||
|
if (d.messageTime == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
d.messageTime = new Date(d.messageTime)
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
const data2 = func(data)
|
||||||
|
return data2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _getNewMessagesAjax(toUser: string, lastMessageTimeStamp: string): Promise<any> {
|
private async _getMessagesAjax(toUser: string, lastMessageTimeStamp: Date): Promise<any> {
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
if (JsonAPI.authToken == null) {
|
if (JsonAPI.authToken == null) {
|
||||||
log.error("authToken null");
|
log.error("authToken null");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
headers.append('X-AUTH-TOKEN', JsonAPI.authToken);
|
headers.append('X-AUTH-TOKEN', JsonAPI.authToken);
|
||||||
const response = await fetch(`${JsonAPI.CHAT_MESSAGES_GET}/${toUser}/${lastMessageTimeStamp}`, {
|
// const url = Sprintf(JsonAPI.CHAT_MESSAGES_GET, toUser, page, 5);
|
||||||
|
// log.debug(url)
|
||||||
|
const response = await fetch(`/api/chat/get/messages/${toUser}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: headers
|
headers: headers
|
||||||
});
|
});
|
||||||
@ -121,6 +143,52 @@ export class ChatModelHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const data: Promise<any> = await response.json();
|
const data: Promise<any> = await response.json();
|
||||||
return data;
|
function func(data: any) {
|
||||||
|
const d1 = data.map((d: any) => {
|
||||||
|
if (d.messageTime == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
d.messageTime = new Date(d.messageTime)
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
const data2 = func(data)
|
||||||
|
return data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _getNewMessagesAjax(toUser: string, lastMessageTimeStamp: Date): Promise<any> {
|
||||||
|
const headers = new Headers();
|
||||||
|
if (JsonAPI.authToken == null) {
|
||||||
|
log.error("authToken null");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
headers.append('X-AUTH-TOKEN', JsonAPI.authToken);
|
||||||
|
// const url = Sprintf(JsonAPI.CHAT_MESSAGES_GET, toUser, page, 5);
|
||||||
|
// log.debug(url)
|
||||||
|
log.debug(lastMessageTimeStamp);
|
||||||
|
log.debug(lastMessageTimeStamp.toISOString())
|
||||||
|
const response = await fetch(`/api/chat/get/messages/${toUser}/${lastMessageTimeStamp.toISOString()}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: headers
|
||||||
|
});
|
||||||
|
log.debug(response.clone());
|
||||||
|
if (fetchErrorHandler(response.clone(), this._notificationService)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const data: Promise<any> = await response.json();
|
||||||
|
function func(data: any) {
|
||||||
|
const d1 = data.map((d: any) => {
|
||||||
|
if (d.messageTime == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
d.messageTime = new Date(d.messageTime)
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
const data2 = func(data)
|
||||||
|
log.debug("LOOK HERE NOW ", data, data2)
|
||||||
|
return data2;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import * as alertify from "alertifyjs";
|
|||||||
import { ActiveUserViewModel } from "../viewmodel/ActiveUserViewModel";
|
import { ActiveUserViewModel } from "../viewmodel/ActiveUserViewModel";
|
||||||
import log = require("loglevel");
|
import log = require("loglevel");
|
||||||
import bootbox = require("bootbox")
|
import bootbox = require("bootbox")
|
||||||
|
import { ChatMessageViewModel } from "../viewmodel/ChatMessageViewModel";
|
||||||
export class AlertifyNotificationService implements NotificationService {
|
export class AlertifyNotificationService implements NotificationService {
|
||||||
|
|
||||||
private readonly _alertify = alertify;
|
private readonly _alertify = alertify;
|
||||||
@ -28,9 +29,8 @@ export class AlertifyNotificationService implements NotificationService {
|
|||||||
message(message: string): void {
|
message(message: string): void {
|
||||||
this._alertify.message(message);
|
this._alertify.message(message);
|
||||||
}
|
}
|
||||||
passphrasePrompt(vm: ActiveUserViewModel, vms: ActiveUserViewModel[], cb1: (contactName: string, passphrase: string,
|
passphrasePrompt(vm: ActiveUserViewModel, vms: ActiveUserViewModel[], cb1: (v: ActiveUserViewModel, op: string) => ChatMessageViewModel[],
|
||||||
lastMessageTime: string | null, op: string) => void,
|
cb2: (...x: any) => any, cb3: (...x: any) => any): void {
|
||||||
cb2: () => any, cb3: (...x: any) => any): void {
|
|
||||||
|
|
||||||
// alertify.myprompt || alertify.dialog('myprompt', function () {
|
// alertify.myprompt || alertify.dialog('myprompt', function () {
|
||||||
|
|
||||||
@ -100,10 +100,19 @@ export class AlertifyNotificationService implements NotificationService {
|
|||||||
log.error("invalid password");
|
log.error("invalid password");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cb1(vm.userName!, result, null, "new");
|
|
||||||
vm.unlocked = true
|
vm.unlocked = true
|
||||||
vms.filter(v => v.userName == vm.userName).map(v => { v.passphrase = result; v.unlocked = true })
|
vm.passphrase = result;
|
||||||
cb2();
|
const chatMessages: ChatMessageViewModel[] = await cb1(vm, "new");
|
||||||
|
log.debug("here", chatMessages)
|
||||||
|
|
||||||
|
vms.filter(v => v.userName == vm.userName).map(v => {
|
||||||
|
v.passphrase = result;
|
||||||
|
v.unlocked = true;
|
||||||
|
v.lastMessageTime = new Date(chatMessages[chatMessages.length - 1].messageTime);
|
||||||
|
})
|
||||||
|
log.debug("last message time = ", chatMessages[chatMessages.length - 1].messageTime)
|
||||||
|
vm.lastMessageTime = new Date(chatMessages[chatMessages.length - 1].messageTime);
|
||||||
|
cb2(vm, vms);
|
||||||
log.debug(vm)
|
log.debug(vm)
|
||||||
log.debug(vms)
|
log.debug(vms)
|
||||||
}
|
}
|
||||||
@ -111,7 +120,11 @@ export class AlertifyNotificationService implements NotificationService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cb1(vm.userName!, vm.passphrase, null, "new");
|
cb1(vm, "new");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log.debug("LOOK HERE",vm.lastMessageTime)
|
||||||
|
// setInterval(this._chatModel.getMessages.bind(this._chatModel,
|
||||||
|
// vm.userName!, vm.passphrase, vm.lastMessageTime!, "new"), 2000);
|
@ -76,6 +76,30 @@ export class ChatView implements Observer<ChatMessageViewModel> {
|
|||||||
scrollTop: $(this._messageContainer)[0].scrollHeight
|
scrollTop: $(this._messageContainer)[0].scrollHeight
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} break;
|
} break;
|
||||||
|
case "update": {
|
||||||
|
const rev: ChatMessageViewModel[] = Object.create(cd.data)
|
||||||
|
// rev.reverse();
|
||||||
|
let arr: string[] = [];
|
||||||
|
rev.forEach((vm: ChatMessageViewModel) => {
|
||||||
|
const vmTemp: ChatMessageViewModel = { ...vm };
|
||||||
|
vmTemp.message = this._markdownService.render(vm.message);
|
||||||
|
/** Very Important!!!
|
||||||
|
* Sanitizing HTML before displaying on webpage to prevent XSS attacks!!
|
||||||
|
*/
|
||||||
|
let rendered;
|
||||||
|
if (vmTemp.fromUser == JsonAPI.principleName) {
|
||||||
|
rendered = DOMPurify.sanitize(this._messageSendTemplate(vmTemp));
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rendered = DOMPurify.sanitize(this._messageReceiveTemplate(vmTemp));
|
||||||
|
}
|
||||||
|
$(this._messageContainer).append(rendered);
|
||||||
|
});
|
||||||
|
// $(this._messageContainer).stop().animate({
|
||||||
|
// scrollTop: $(this._messageContainer)[0].scrollHeight
|
||||||
|
// }, 1500);
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
const rev: ChatMessageViewModel[] = Object.create(cd.data)
|
const rev: ChatMessageViewModel[] = Object.create(cd.data)
|
||||||
rev.reverse();
|
rev.reverse();
|
||||||
@ -137,8 +161,10 @@ export class ChatView implements Observer<ChatMessageViewModel> {
|
|||||||
|
|
||||||
|
|
||||||
const chatInput = document.getElementById('chatInput') as HTMLInputElement;
|
const chatInput = document.getElementById('chatInput') as HTMLInputElement;
|
||||||
const passphraseInput = document.getElementById('passphrase') as HTMLInputElement;
|
const vm = this._userModel.activeUsersList.find(u => u.userName == JsonAPI.contactName);
|
||||||
const passphrase = this._userModel.activeUsersList.find(u => u.userName == JsonAPI.contactName)?.passphrase
|
// new Date().
|
||||||
|
vm!.lastMessageTime = new Date();
|
||||||
|
const passphrase = vm?.passphrase
|
||||||
|
|
||||||
if (chatInput.value == '' || chatInput.value == null) {
|
if (chatInput.value == '' || chatInput.value == null) {
|
||||||
this._notificationService.error("Please enter a message");
|
this._notificationService.error("Please enter a message");
|
||||||
@ -200,9 +226,10 @@ export class ChatView implements Observer<ChatMessageViewModel> {
|
|||||||
if ($(this._messageContainer).scrollTop() == 0 && $(this._messageContainer).html() != "") {
|
if ($(this._messageContainer).scrollTop() == 0 && $(this._messageContainer).html() != "") {
|
||||||
let currentMsg = $('.msg:first');
|
let currentMsg = $('.msg:first');
|
||||||
log.debug('Reached top')
|
log.debug('Reached top')
|
||||||
let ab = this._userModel.activeUsersList.find(u => u.userName == JsonAPI.contactName)
|
const vm = this._userModel.activeUsersList.find(u => u.userName == JsonAPI.contactName)
|
||||||
if (JsonAPI.contactName != null)
|
if (JsonAPI.contactName != null)
|
||||||
this._chatModel.getMessages(JsonAPI.contactName, ab!.passphrase, null, "page").then(() => {
|
|
||||||
|
this._chatModel.getMessages(vm!, "page").then(() => {
|
||||||
if (currentMsg != null) {
|
if (currentMsg != null) {
|
||||||
// log.debug(currentMsg.offset()!.top)
|
// log.debug(currentMsg.offset()!.top)
|
||||||
$(this._messageContainer).scrollTop(currentMsg.position().top - $('.msg').position()!.top)
|
$(this._messageContainer).scrollTop(currentMsg.position().top - $('.msg').position()!.top)
|
||||||
|
@ -23,6 +23,7 @@ export class UserView implements Observer<ActiveUserViewModel> {
|
|||||||
private readonly _userContactOnlineTemplate: Handlebars.TemplateDelegate<ActiveUserViewModel>;
|
private readonly _userContactOnlineTemplate: Handlebars.TemplateDelegate<ActiveUserViewModel>;
|
||||||
private readonly _userContactOfflineTemplate: Handlebars.TemplateDelegate<ActiveUserViewModel>;
|
private readonly _userContactOfflineTemplate: Handlebars.TemplateDelegate<ActiveUserViewModel>;
|
||||||
private readonly _notificationService: NotificationService;
|
private readonly _notificationService: NotificationService;
|
||||||
|
private _newMessagesLoop: any;
|
||||||
|
|
||||||
constructor(deps: UserViewDeps) {
|
constructor(deps: UserViewDeps) {
|
||||||
this._model = deps.model;
|
this._model = deps.model;
|
||||||
@ -65,6 +66,7 @@ export class UserView implements Observer<ActiveUserViewModel> {
|
|||||||
|
|
||||||
private _userCallBack(el: Element): void {
|
private _userCallBack(el: Element): void {
|
||||||
this._chatModel.clear();
|
this._chatModel.clear();
|
||||||
|
clearInterval(this._newMessagesLoop);
|
||||||
let current = document.getElementsByClassName('user-box active');
|
let current = document.getElementsByClassName('user-box active');
|
||||||
|
|
||||||
let passphrase: string = '';
|
let passphrase: string = '';
|
||||||
@ -122,12 +124,19 @@ export class UserView implements Observer<ActiveUserViewModel> {
|
|||||||
this._promptHandler.bind(this), this._chatModel.isPassphraseValid.bind(this._chatModel));
|
this._promptHandler.bind(this), this._chatModel.isPassphraseValid.bind(this._chatModel));
|
||||||
// this._chatModel.getMessages(userName, vm.passphrase, null, "new");
|
// this._chatModel.getMessages(userName, vm.passphrase, null, "new");
|
||||||
el.className += " active";
|
el.className += " active";
|
||||||
|
log.debug("loop", this._newMessagesLoop)
|
||||||
|
if (this._newMessagesLoop != null) {
|
||||||
|
this._newMessagesLoop = setInterval(this._chatModel.getMessages.bind(this._chatModel,
|
||||||
|
vm, "update"), 2000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _promptHandler(vm: ActiveUserViewModel, vms: ActiveUserViewModel[]) {
|
private _promptHandler(vm: ActiveUserViewModel, vms: ActiveUserViewModel[]) {
|
||||||
// vms.filter(v => v.userName == vm.userName).map(v => v.userName = vm.userName)
|
// vms.filter(v => v.userName == vm.userName).map(v => v.userName = vm.userName)
|
||||||
log.debug(vms)
|
log.debug(vms)
|
||||||
this._model.notify();
|
this._model.notify();
|
||||||
|
this._newMessagesLoop = setInterval(this._chatModel.getMessages.bind(this._chatModel,
|
||||||
|
vm, "update"), 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addSearchButtonEL() {
|
private _addSearchButtonEL() {
|
||||||
|
@ -4,4 +4,5 @@ export class ActiveUserViewModel {
|
|||||||
unlocked: boolean = false;
|
unlocked: boolean = false;
|
||||||
passphrase: string = "";
|
passphrase: string = "";
|
||||||
lastActive: Date | undefined;
|
lastActive: Date | undefined;
|
||||||
|
lastMessageTime: Date | undefined;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user