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 log = require('loglevel');
|
||||
import { ObserverData } from "../observe/ObserverData";
|
||||
import { ActiveUserViewModel } from "../viewmodel/ActiveUserViewModel";
|
||||
|
||||
interface Params {
|
||||
userName: string,
|
||||
@ -44,10 +45,11 @@ export class ChatModel implements Subject<ChatMessageViewModel> {
|
||||
|
||||
private storeUserMessages(username: string, messages: ChatMessageViewModel[], op: string) {
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
@ -86,6 +88,12 @@ export class ChatModel implements Subject<ChatMessageViewModel> {
|
||||
observer.update(od);
|
||||
}
|
||||
} 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") }
|
||||
}
|
||||
}
|
||||
@ -100,28 +108,31 @@ export class ChatModel implements Subject<ChatMessageViewModel> {
|
||||
this.notify({ userName: "", data: [], op: "clear" })
|
||||
}
|
||||
|
||||
public async getMessages(contactName: string, passphrase: string, lastMessageTime: string | null, op: string): Promise<ChatMessageViewModel[]> {
|
||||
if (this._messagePageMap.get(contactName) == null)
|
||||
this._messagePageMap.set(contactName, 0);
|
||||
public async getMessages(vm: ActiveUserViewModel, op: string): Promise<ChatMessageViewModel[]> {
|
||||
if (this._messagePageMap.get(vm.userName!) == null)
|
||||
this._messagePageMap.set(vm.userName!, 0);
|
||||
|
||||
const pageNumber = this._messagePageMap.get(contactName)
|
||||
const cVMs = await this._chatModelHelper.getMessages(contactName, passphrase, pageNumber!, lastMessageTime, op);
|
||||
const pageNumber = this._messagePageMap.get(vm.userName!)
|
||||
const cVMs = await this._chatModelHelper.getMessages(vm.userName!, vm.passphrase, pageNumber!, vm.lastMessageTime!, op);
|
||||
if (cVMs != null) {
|
||||
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(existingMessages);
|
||||
log.debug('new messages:')
|
||||
log.debug(cVMs);
|
||||
this.storeUserMessages(contactName, cVMs, op);
|
||||
this.notify({ userName: contactName, data: cVMs, op: op });
|
||||
this.storeUserMessages(vm.userName!, cVMs, op);
|
||||
this.notify({ userName: vm.userName!, data: cVMs, op: op });
|
||||
}
|
||||
else {
|
||||
log.error('Messages were null');
|
||||
}
|
||||
|
||||
if (cVMs.length != 0) {
|
||||
this._messagePageMap.set(contactName, this._messagePageMap.get(contactName)! + 1);
|
||||
if (cVMs.length != 0 && op == "update") vm.lastMessageTime = cVMs[cVMs.length - 1].messageTime;
|
||||
|
||||
if (cVMs.length != 0 && op != "update") {
|
||||
|
||||
this._messagePageMap.set(vm.userName!, this._messagePageMap.get(vm.userName!)! + 1);
|
||||
}
|
||||
|
||||
return cVMs;
|
||||
|
@ -18,23 +18,32 @@ export class ChatModelHelper {
|
||||
}
|
||||
|
||||
|
||||
public async getMessages(userName: string, passphrase: string, page: number | null, lastMessageTime: string | null, op: string): Promise<ChatMessageViewModel[]> {
|
||||
switch (lastMessageTime) {
|
||||
case null: {
|
||||
const data: ChatMessageDTO[] = await this._getPaginatedMessagesAjax(userName, page!);
|
||||
const cVMs = Promise.all(data.map(vm => this._toChatMessageVMAsync(vm, passphrase)).reverse());
|
||||
return cVMs;
|
||||
public async getMessages(userName: string, passphrase: string, page: number | null, lastMessageTime: Date | null, op: string): Promise<ChatMessageViewModel[]> {
|
||||
switch (op) {
|
||||
case "page": {
|
||||
const data: ChatMessageDTO[] = await this._getPaginatedMessagesAjax(userName, page!);
|
||||
const cVMs = Promise.all(data.map(vm => this._toChatMessageVMAsync(vm, passphrase)).reverse());
|
||||
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!);
|
||||
return data.map(vm => this._toChatMessageVM(vm, passphrase));
|
||||
}
|
||||
default: {
|
||||
log.error("Invalid operation");
|
||||
return Array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async isPassphraseValid(passphrase: string, userName: string): Promise<boolean> {
|
||||
const messages: ChatMessageDTO[] = await this._getPaginatedMessagesAjax(userName, 0);
|
||||
if(messages.length === 0) return true;
|
||||
if (messages.length === 0) return true;
|
||||
try {
|
||||
this._encryptionService.decrypt(passphrase, messages[0].messageCipher)
|
||||
} catch (error) {
|
||||
@ -102,17 +111,30 @@ export class ChatModelHelper {
|
||||
return null;
|
||||
}
|
||||
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();
|
||||
if (JsonAPI.authToken == null) {
|
||||
log.error("authToken null");
|
||||
return;
|
||||
};
|
||||
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',
|
||||
headers: headers
|
||||
});
|
||||
@ -121,6 +143,52 @@ export class ChatModelHelper {
|
||||
return null;
|
||||
}
|
||||
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 log = require("loglevel");
|
||||
import bootbox = require("bootbox")
|
||||
import { ChatMessageViewModel } from "../viewmodel/ChatMessageViewModel";
|
||||
export class AlertifyNotificationService implements NotificationService {
|
||||
|
||||
private readonly _alertify = alertify;
|
||||
@ -28,9 +29,8 @@ export class AlertifyNotificationService implements NotificationService {
|
||||
message(message: string): void {
|
||||
this._alertify.message(message);
|
||||
}
|
||||
passphrasePrompt(vm: ActiveUserViewModel, vms: ActiveUserViewModel[], cb1: (contactName: string, passphrase: string,
|
||||
lastMessageTime: string | null, op: string) => void,
|
||||
cb2: () => any, cb3: (...x: any) => any): void {
|
||||
passphrasePrompt(vm: ActiveUserViewModel, vms: ActiveUserViewModel[], cb1: (v: ActiveUserViewModel, op: string) => ChatMessageViewModel[],
|
||||
cb2: (...x: any) => any, cb3: (...x: any) => any): void {
|
||||
|
||||
// alertify.myprompt || alertify.dialog('myprompt', function () {
|
||||
|
||||
@ -100,10 +100,19 @@ export class AlertifyNotificationService implements NotificationService {
|
||||
log.error("invalid password");
|
||||
return;
|
||||
}
|
||||
cb1(vm.userName!, result, null, "new");
|
||||
vm.unlocked = true
|
||||
vms.filter(v => v.userName == vm.userName).map(v => { v.passphrase = result; v.unlocked = true })
|
||||
cb2();
|
||||
vm.passphrase = result;
|
||||
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(vms)
|
||||
}
|
||||
@ -111,7 +120,11 @@ export class AlertifyNotificationService implements NotificationService {
|
||||
});
|
||||
}
|
||||
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
|
||||
}, 1500);
|
||||
} 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: {
|
||||
const rev: ChatMessageViewModel[] = Object.create(cd.data)
|
||||
rev.reverse();
|
||||
@ -137,8 +161,10 @@ export class ChatView implements Observer<ChatMessageViewModel> {
|
||||
|
||||
|
||||
const chatInput = document.getElementById('chatInput') as HTMLInputElement;
|
||||
const passphraseInput = document.getElementById('passphrase') as HTMLInputElement;
|
||||
const passphrase = this._userModel.activeUsersList.find(u => u.userName == JsonAPI.contactName)?.passphrase
|
||||
const vm = this._userModel.activeUsersList.find(u => u.userName == JsonAPI.contactName);
|
||||
// new Date().
|
||||
vm!.lastMessageTime = new Date();
|
||||
const passphrase = vm?.passphrase
|
||||
|
||||
if (chatInput.value == '' || chatInput.value == null) {
|
||||
this._notificationService.error("Please enter a message");
|
||||
@ -155,13 +181,13 @@ export class ChatView implements Observer<ChatMessageViewModel> {
|
||||
const messageContent = chatInput.value;
|
||||
const msgTime = new Date();
|
||||
const context: ChatMessageViewModel = {
|
||||
fromUser: JsonAPI.principleName || "error",
|
||||
fromUser: JsonAPI.principleName || "error",
|
||||
toUser: "",
|
||||
message: messageContent,
|
||||
messageTime: msgTime
|
||||
};
|
||||
|
||||
this.update({data: new Array(context), op: "new"})
|
||||
this.update({ data: new Array(context), op: "new" })
|
||||
|
||||
let messageCipher: MessageCipherDTO = this._encryptionService.encrypt(passphrase!, messageContent)
|
||||
let chatMessageDTO = {
|
||||
@ -200,9 +226,10 @@ export class ChatView implements Observer<ChatMessageViewModel> {
|
||||
if ($(this._messageContainer).scrollTop() == 0 && $(this._messageContainer).html() != "") {
|
||||
let currentMsg = $('.msg:first');
|
||||
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)
|
||||
this._chatModel.getMessages(JsonAPI.contactName, ab!.passphrase, null, "page").then(() => {
|
||||
|
||||
this._chatModel.getMessages(vm!, "page").then(() => {
|
||||
if (currentMsg != null) {
|
||||
// log.debug(currentMsg.offset()!.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 _userContactOfflineTemplate: Handlebars.TemplateDelegate<ActiveUserViewModel>;
|
||||
private readonly _notificationService: NotificationService;
|
||||
private _newMessagesLoop: any;
|
||||
|
||||
constructor(deps: UserViewDeps) {
|
||||
this._model = deps.model;
|
||||
@ -65,6 +66,7 @@ export class UserView implements Observer<ActiveUserViewModel> {
|
||||
|
||||
private _userCallBack(el: Element): void {
|
||||
this._chatModel.clear();
|
||||
clearInterval(this._newMessagesLoop);
|
||||
let current = document.getElementsByClassName('user-box active');
|
||||
|
||||
let passphrase: string = '';
|
||||
@ -122,12 +124,19 @@ export class UserView implements Observer<ActiveUserViewModel> {
|
||||
this._promptHandler.bind(this), this._chatModel.isPassphraseValid.bind(this._chatModel));
|
||||
// this._chatModel.getMessages(userName, vm.passphrase, null, "new");
|
||||
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[]) {
|
||||
// vms.filter(v => v.userName == vm.userName).map(v => v.userName = vm.userName)
|
||||
log.debug(vms)
|
||||
this._model.notify();
|
||||
this._newMessagesLoop = setInterval(this._chatModel.getMessages.bind(this._chatModel,
|
||||
vm, "update"), 2000);
|
||||
}
|
||||
|
||||
private _addSearchButtonEL() {
|
||||
|
@ -4,4 +4,5 @@ export class ActiveUserViewModel {
|
||||
unlocked: boolean = false;
|
||||
passphrase: string = "";
|
||||
lastActive: Date | undefined;
|
||||
lastMessageTime: Date | undefined;
|
||||
}
|
Loading…
Reference in New Issue
Block a user