import { Injectable } from '@angular/core'; import { WsChatService } from 'src/app/services/chat/ws-chat.service'; import { MessageService } from 'src/app/services/chat/message.service'; import { showDateDuration } from 'src/plugin/showDateDuration'; import { ToastsService } from '../toast.service'; import { chatHistory } from 'src/app/models/chatMethod'; import { Storage } from '@ionic/storage'; import { Platform } from '@ionic/angular'; import { SqliteService } from 'src/app/services/sqlite.service'; import { NativeNotificationService } from 'src/app/services/native-notification.service'; import { SessionStore } from 'src/app/store/session.service'; import { capitalizeTxt } from 'src/plugin/text' import { SortService } from '../functions/sort.service'; import { chatUser } from 'src/app/models/chatMethod'; import { environment } from 'src/environments/environment'; import { ChatService } from 'src/app/services/chat.service'; import { NfService } from 'src/app/services/chat/nf.service'; import { v4 as uuidv4 } from 'uuid' @Injectable({ providedIn: 'root' }) export class RoomService { messages: MessageService[] = [] storageMessage: any[] = []; lastMessage: MessageService; customFields: any; id = '' t = '' name = '' _updatedAt = {} hasLoadHistory = false duration = '' isTyping = false otherUserType = false lastTimeType = null message = '' lastMessageTxt = '' userThatIsTyping = '' private ToastService = ToastsService mgsArray = []; messagesLocalReference = [] scrollDown = () => { } /** * @description get user list from ws-chat-methods.service * @returns chatUser[] */ getAllUsers = (): chatUser[] => { return [] } sortRoomList = () => {} uploadAttachment = (formData) => {} constructor( public WsChatService: WsChatService, private MessageService: MessageService, private storage: Storage, private platform: Platform, private sqlservice: SqliteService, private NativeNotificationService: NativeNotificationService, private sortService: SortService, private chatService: ChatService, private NfService: NfService ) { this.NativeNotificationService.askForPermission() } setData({ customFields, id, name, t, lastMessage = new MessageService(this.storage, this.NfService, this.WsChatService), _updatedAt }) { this.customFields = customFields this.id = id this.name = name this.t = t this.lastMessage = lastMessage this._updatedAt = _updatedAt this.calDateDuration() } isSenderIsNotMe(ChatMessage) { return SessionStore.user.RochetChatUser != ChatMessage.u.username } receiveMessage() { this.WsChatService.updateRoomEventss( this.id, "stream-room-messages", (_ChatMessage) => { console.log('recivemessage', _ChatMessage) alert('receive and send to view') setTimeout(()=>{ let ChatMessage = _ChatMessage.fields.args[0] ChatMessage = this.fix_updatedAt(ChatMessage) const message = this.prepareMessage(ChatMessage) this.lastMessage = message this.calDateDuration(ChatMessage._updatedAt) if (message.t == 'r') { this.name = message.msg } if(this.isSenderIsNotMe(ChatMessage)) { this.NativeNotificationService.sendNotificationChat({ message: message.msg, title: this.name }); } this.addMessageDB(ChatMessage) setTimeout(()=>{ this.scrollDown() }, 50) }, 150) } ) this.WsChatService.receiveStreamNotifyRoom((message) => { if(message.fields.eventName == this.id+'/'+'typing') { this.userThatIsTyping = this.usernameToDisplayName(message.fields.args[0]) console.log(this.userThatIsTyping, 'this.userThatIsTyping') this.isTyping = message.fields.args[1] this.otherUserType = message.fields.args[1] } else if (message.fields.eventName == this.id+'/'+'deleteMessage') {} }) } async addMessageDB(ChatMessage) { if (environment.chatOffline) { this.storage.get('chatmsg' + this.id).then((messages: any = []) => { if(!Array.isArray(messages)) { messages = [] } if(!ChatMessage._id && environment.chatOffline) { delete ChatMessage.temporaryData messages.push(ChatMessage) this.storage.set('chatmsg' + this.id, messages) } else { const find = messages.find((message)=> { return message._id == ChatMessage._id }) if(!find) { delete ChatMessage.temporaryData messages.push(ChatMessage) this.storage.set('chatmsg' + this.id, messages) } } }) } } async updateMessageDB(ChatMessage, localReference) { if (environment.chatOffline) { this.storage.get('chatmsg' + this.id).then((messages: any = []) => { if(!Array.isArray(messages)) { messages = [] } let index; const find = messages.find((message, _index)=> { if(message.localReference) { if(message.localReference == ChatMessage.localReference) { index = _index return true } } return false }) if(find) { messages[index] = ChatMessage this.storage.set('chatmsg' + this.id, messages) } }) } } /** * @description delete message in the DB. get all messages, delete then corresponding message and update the store * @param id message ID */ private deleteMessageFromDb(id) { if (environment.chatOffline) { this.storage.get('chatmsg' + this.id).then((messages: any = []) => { if(!Array.isArray(messages)) { messages = [] } messages.forEach((message, index) => { if(message._id == id) { messages.splice(index, 1) } }) this.storage.set('chatmsg' + this.id, messages).then((value) => { console.log('MSG SAVED ON STORAGE', value) }); }) } } async receiveMessageDelete() { this.WsChatService.updateRoomEventss( this.id, "stream-notify-room", async (ChatMessage) => { const DeletedMessageId = ChatMessage.fields.args[0]._id; console.log(DeletedMessageId); this.deleteMessage(DeletedMessageId) } ) } /** * @description delete message in the view * @param id message ID */ deleteMessage(id) { this.messages.forEach((message, index) => { if(message._id == id) { this.messages.splice(index, 1) this.deleteMessageFromDb(id) //Get previous last message from room const previousLastMessage = this.messages.slice(-1)[0]; this.lastMessage = previousLastMessage; this.calDateDuration(previousLastMessage._updatedAt) } }) } /** * @description sen text message */ async send({file = null, attachments = null, temporaryData = {}}) { const localReference = uuidv4() + 'peter' let offlineChatMessage = { rid: this.id, msg: this.message, attachments, file, temporaryData, localReference } const message: MessageService = this.prepareMessage(offlineChatMessage, environment.chatOffline) setTimeout(() => { this.scrollDown() }, 150) message.send().then((ChatMessage) => { this.updateMessageDB(ChatMessage, localReference) }) if (environment.chatOffline) { this.messagesLocalReference.push(localReference) this.addMessageDB(offlineChatMessage) setTimeout(() => { this.scrollDown() }, 150) this.lastMessage = message this.calDateDuration(message._updatedAt) this.sortRoomList() } this.message= '' } redefinedMessage (message: MessageService, ChatMessage) { ChatMessage = this.fix_updatedAt(ChatMessage) message.setData(ChatMessage) if( new Date(this.lastMessage._updatedAt).getTime() < new Date(message._updatedAt).getTime()) { this.lastMessage = message this.calDateDuration(message._updatedAt) } this.sortRoomList() } sendTyping(text:string = this.message) { if(this.lastMessageTxt == text) { return false } this.lastTimeType = new Date().getTime() const lastIsTyping = this.isTyping if(text.length >= 1) { this.isTyping = true } else { this.isTyping = false } if(lastIsTyping != this.isTyping) { this.WsChatService.sendStreamNotifyRoom(this.id, SessionStore.user.RochetChatUser, 'typing', this.isTyping) } this.lastMessageTxt = this.message this.typingWatch() } private typingWatch() { setTimeout(()=>{ const now = new Date().getTime() if((now - this.lastTimeType) >= 2888) { if(this.isTyping == true) { this.isTyping = false this.WsChatService.sendStreamNotifyRoom(this.id, SessionStore.user.RochetChatUser, 'typing', this.isTyping) } } else { //console.log(now - this.lastTimeType) } }, 3000) } private setTypingOff() { this.sendTyping('') } roomLeave() { this.setTypingOff() } open() { // this.typing(this.message) } leave(rid?) { this.WsChatService.leaveRoom(this.id) } isJson(str) { try { JSON.parse(str); } catch (e) { return ""; } return JSON.parse(str); } async restoreMessageFromDB() { if(environment.chatOffline) { await this.storage.get('chatmsg' + this.id).then( async (messages = []) => { if(!Array.isArray(messages)) { messages = [] } await messages.forEach( async (ChatMessage, index) => { const wewMessage = this.prepareMessage(ChatMessage, false) if(wewMessage.offline == false) { this.prepareMessage(ChatMessage) } else { if(environment.chatOffline) alert('create offline') const offlineMessage = this.prepareMessage(ChatMessage) offlineMessage.send().then(()=>{ this.updateMessageDB(ChatMessage, ChatMessage.localReference) }) } }); setTimeout(()=> { this.scrollDown() }, 50) }) } } // runs onces only async loadHistory({limit = 50, forceUpdate = false }) { if(forceUpdate == false) { if (this.hasLoadHistory) { return false } } await this.restoreMessageFromDB() await this.WsChatService.loadHistory(this.id, limit).then( async (chatHistory:chatHistory) => { console.log('loadHistory', chatHistory) await chatHistory.result.messages.reverse().forEach( async (message) => { this.prepareMessage(message) this.messages = this.sortService.sortDate(this.messages, '_updatedAt') }) this.storage.set('chatmsg' + this.id, chatHistory.result.messages) }) setTimeout(() => { this.scrollDown() }, 50) this.hasLoadHistory = true } prepareMessage(message, save = true): MessageService { message = this.fix_updatedAt(message) const wewMessage = new MessageService(this.storage, this.NfService, this.WsChatService) wewMessage.setData(message) wewMessage.loadHistory = this.hasLoadHistory if(!message._id && environment.chatOffline) { if(this.hasLoadHistory && environment.chatOffline) alert('create offline') this.messages.push(wewMessage) return wewMessage } const found = this.messages.find((MessageService) => { if (MessageService._id == message._id) { if(this.hasLoadHistory) console.log(`${MessageService._id} == ${message._id}`) return true } else { return false } }) if (save && !found) { if(this.hasLoadHistory && environment.chatOffline) alert('not found') this.messages.push(wewMessage) } return wewMessage } private calDateDuration(date = null) { this.duration = showDateDuration(date || this._updatedAt); this._updatedAt = date || this._updatedAt } private fix_updatedAt(message) { if (message.result) { message.result._updatedAt = message.result._updatedAt['$date'] } else if(message._updatedAt) { if(message._updatedAt.hasOwnProperty('$date')) { message._updatedAt = message._updatedAt['$date'] } } return message } usernameToDisplayName(username) { const firstName = capitalizeTxt(username.split('.')[0]) const lastName = capitalizeTxt(username.split('.')[1]) return firstName + ' ' + lastName } }