diff --git a/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts b/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts index 98a68ebc0..0479dc0a8 100644 --- a/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts +++ b/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts @@ -26,7 +26,7 @@ export function messageListDetermineChanges(serverList: MessageTable[], localLis item.$id = localItem.$id } - return localItem && (item.editedAt !== localItem.editedAt || item.reactions.some((r, index) => { + return localItem && (item.editedAt !== localItem.editedAt || item.sentAt != item.sentAt || item.reactions.some((r, index) => { const localReaction = localItem.reactions[index]; return !localReaction || r.reactedAt !== localReaction.reactedAt; })); diff --git a/src/app/module/chat/data/repository/message/message-local-data-source.service.ts b/src/app/module/chat/data/repository/message/message-local-data-source.service.ts index e23ec12e7..b3a5788a1 100644 --- a/src/app/module/chat/data/repository/message/message-local-data-source.service.ts +++ b/src/app/module/chat/data/repository/message/message-local-data-source.service.ts @@ -76,11 +76,11 @@ export class MessageLocalDataSourceService extends DexieRepository { - return chatDatabase.message.where('roomId').equals(roomId).sortBy('$createAt') as any + return chatDatabase.message.where('roomId').equals(roomId).sortBy('sentAt') as any } getItemsLive(roomId: string): DexieObservable { - return liveQuery(() => chatDatabase.message.where('roomId').equals(roomId).sortBy('$createAt') as any) + return liveQuery(() => chatDatabase.message.where('roomId').equals(roomId).sortBy('sentAt') as any) } async getOfflineMessages () { diff --git a/src/app/module/chat/data/repository/room/room-local-repository.service.ts b/src/app/module/chat/data/repository/room/room-local-repository.service.ts index 1b9f42c86..123778457 100644 --- a/src/app/module/chat/data/repository/room/room-local-repository.service.ts +++ b/src/app/module/chat/data/repository/room/room-local-repository.service.ts @@ -13,19 +13,14 @@ export class RoomLocalRepository extends DexieRepository i constructor() { super(chatDatabase.room, RoomTableSchema) - // chatDatabase.room.hook('creating', (primaryKey, obj, transaction) => { - // if(obj.messages?.[0].attachments?.[0]) { - // delete obj.messages[0].attachments[0].file - // } - // }); chatDatabase.room.hook('updating', (modifications, primKey, oldValue, transaction) => { - if((modifications as Partial).messages?.[0].requestId == oldValue.messages?.[0].requestId) { - (modifications as Partial).messages[0].sentAt = oldValue.messages?.[0]?.sentAt; - } else if ((modifications as Partial).messages?.[0].id == oldValue.messages?.[0].id) { - (modifications as Partial).messages[0].sentAt = oldValue.messages?.[0]?.sentAt - } + // if((modifications as Partial).messages?.[0].requestId == oldValue.messages?.[0].requestId) { + // (modifications as Partial).messages[0].sentAt = oldValue.messages?.[0]?.sentAt; + // } else if ((modifications as Partial).messages?.[0].id == oldValue.messages?.[0].id) { + // (modifications as Partial).messages[0].sentAt = oldValue.messages?.[0]?.sentAt + // } return modifications }); diff --git a/src/app/module/chat/domain/chat-service.service.ts b/src/app/module/chat/domain/chat-service.service.ts index e810c02dc..383043a06 100644 --- a/src/app/module/chat/domain/chat-service.service.ts +++ b/src/app/module/chat/domain/chat-service.service.ts @@ -148,8 +148,8 @@ export class ChatServiceService { } async start() { - await this.chatSync() - await this.SocketConnectUseCaseService.execute(); + this.chatSync() + this.SocketConnectUseCaseService.execute(); } diff --git a/src/app/module/chat/domain/use-case/message/sync-all-room-messages.service.ts b/src/app/module/chat/domain/use-case/message/sync-all-room-messages.service.ts index 036c9cf6a..33b216395 100644 --- a/src/app/module/chat/domain/use-case/message/sync-all-room-messages.service.ts +++ b/src/app/module/chat/domain/use-case/message/sync-all-room-messages.service.ts @@ -5,10 +5,8 @@ import { MessageRemoteDataSourceService } from '../../../data/repository/message import { MessageSocketRepositoryService } from '../../../data/repository/message/message-live-signalr-data-source.service'; import { ok } from 'neverthrow'; import { RoomLocalRepository } from '../../../data/repository/room/room-local-repository.service'; -import { SessionStore } from 'src/app/store/session.service'; import { Logger } from 'src/app/services/logger/main/service'; import { XTracerAsync, TracingType } from 'src/app/services/monitoring/opentelemetry/tracer'; -import { v4 as uuidv4 } from 'uuid' import { MessageTable } from 'src/app/infra/database/dexie/instance/chat/schema/message'; @Injectable({ @@ -51,7 +49,7 @@ export class SyncAllRoomMessagesService { for (const message of changedItems) { delete message.sentAt let clone: MessageTable = { ...message, roomId: room.id }; - await this.messageLocalDataSourceService.update(clone.$id, clone); + this.messageLocalDataSourceService.update(clone.$id, clone); // const me = message.info.find(e => e.memberId === SessionStore.user.UserId && typeof e.deliverAt === 'string'); @@ -72,7 +70,7 @@ export class SyncAllRoomMessagesService { // You can perform operations with addedItems here if needed } - await this.messageLocalDataSourceService.insertMany(addedItems.reverse().map(e => { + this.messageLocalDataSourceService.insertMany(addedItems.reverse().map(e => { e.origin = 'history' return e })); diff --git a/src/app/module/chat/domain/use-case/room/room-set-last-message.service.ts b/src/app/module/chat/domain/use-case/room/room-set-last-message.service.ts index b6ead587c..d9f253ce3 100644 --- a/src/app/module/chat/domain/use-case/room/room-set-last-message.service.ts +++ b/src/app/module/chat/domain/use-case/room/room-set-last-message.service.ts @@ -41,6 +41,7 @@ export class RoomSetLastMessageService { for(const room of roomList) { if(room.messages?.[0]?.id == message.id) { + console.log('listenToUpdateMessage', message.roomId) const result = await this.roomLocalRepository.update(message.roomId, { messages: [message] }) @@ -67,6 +68,7 @@ export class RoomSetLastMessageService { map(message => Object.assign(new MessageEntity(), message)) ).subscribe(async (message) => { if(message?.roomId) { + console.log('listenToIncomingMessage', message.roomId) const result = await this.roomLocalRepository.update(message.roomId, { messages: [message] }) @@ -88,9 +90,11 @@ export class RoomSetLastMessageService { if(message?.roomId) { setTimeout(async() => { - const result = await this.roomLocalRepository.update(message.roomId, { - messages: [message] - }) + if(message.origin != 'history') { + const result = await this.roomLocalRepository.update(message.roomId, { + messages: [message] + }) + } }, 100) } diff --git a/src/app/ui/chat/component/messages/messages.page.ts b/src/app/ui/chat/component/messages/messages.page.ts index e694a77e4..1fd2f1e20 100644 --- a/src/app/ui/chat/component/messages/messages.page.ts +++ b/src/app/ui/chat/component/messages/messages.page.ts @@ -333,6 +333,11 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy this.messages1[this.roomId].push(msg) } } + + + this.messages1[this.roomId].sort((a, b) => { + return new Date(a.sentAt).getTime() - new Date(b.sentAt).getTime() + }) }) } @@ -1471,9 +1476,6 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy } - } else { - this.openFile(msg.attachments[0].safeFile, msg.attachments[0].description, msg.attachments[0].mimeType); - // this.downloadFileFromBrowser("file", str) } } diff --git a/src/app/ui/chat/modal/messages/messages.page.html b/src/app/ui/chat/modal/messages/messages.page.html index 1112debbc..80150f7d8 100644 --- a/src/app/ui/chat/modal/messages/messages.page.html +++ b/src/app/ui/chat/modal/messages/messages.page.html @@ -117,7 +117,7 @@ -
+
diff --git a/src/app/ui/chat/modal/messages/messages.page.ts b/src/app/ui/chat/modal/messages/messages.page.ts index 0d06aa97e..231c2ca7a 100644 --- a/src/app/ui/chat/modal/messages/messages.page.ts +++ b/src/app/ui/chat/modal/messages/messages.page.ts @@ -52,7 +52,9 @@ import { tap } from 'rxjs/operators'; import { ChatPopoverPage } from '../chat-popover/chat-popover.page'; import { ViewOncesImagePageInput, ViewOncesImagePage } from '../view-onces/view-onces.page'; import { LastMessage } from '../../utils/lastMessage'; - +import { File } from '@awesome-cordova-plugins/file/ngx'; +import { Filesystem, Directory } from '@capacitor/filesystem'; +import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx'; const IMAGE_DIR = 'stored-images'; @@ -168,6 +170,8 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { private userTypingLocalRepository: UserTypingLocalRepository, private UserTypingRemoteRepositoryService: UserTypingRemoteRepositoryService, private messageLocalDataSourceService: MessageLocalDataSourceService, + private file: File, + private fileOpener: FileOpener, ) { @@ -1263,59 +1267,133 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { } - async openFile(pdfString, filename, type) { +// async openFile(pdfString, filename, type) { - console.log('url while open ',pdfString) +// console.log('url while open ',pdfString) - /* const modal = await this.modalController.create({ - component: ViewDocumentSecondOptionsPage, - componentProps: { - fileUrl: pdfString, - filename: filename - }, - cssClass: 'modal modal-desktop' +// /* const modal = await this.modalController.create({ +// component: ViewDocumentSecondOptionsPage, +// componentProps: { +// fileUrl: pdfString, +// filename: filename +// }, +// cssClass: 'modal modal-desktop' +// }); +// await modal.present(); +// /* +// await modal.present(); */ + +// // var blob = new Blob([pdfString], { type: 'application/pdf' }); + + +// let pathFile = '' +// const fileName = filename +// if (this.platform.is('ios')) { +// pathFile = this.file.documentsDirectory +// } else { +// pathFile = this.file.externalRootDirectory +// } + +// console.log('file data', pdfString) +// console.log(pathFile) + +// let removePre = this.removeTextBeforeSlash(pdfString,',') +// console.log('file data remove ', removePre) + +// await Filesystem.writeFile({ +// path: fileName, +// data: removePre, +// directory: Directory.Cache, +// }).then((dir) => { +// console.log('DIR ', dir) +// this.fileOpener +// .open(dir.uri, type) +// .then(() => console.log()) +// .catch(e => console.error(e)) +// }).catch((error) => { +// console.log('error writing the file', error) +// }); +// } + + async fetchBlobFromURL(blobUrl: string): Promise { + try { + const response = await fetch(blobUrl); + if (!response.ok) { + throw new Error(`Failed to fetch blob: ${response.statusText}`); + } + return await response.blob(); + } catch (error) { + console.error('Error fetching blob from URL:', error); + throw error; + } + } + + convertBlobToDataURL(blob: Blob): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => { + if (reader.result) { + resolve(reader.result as string); + } else { + reject('Conversion failed'); + } + }; + reader.onerror = (error) => reject(error); + reader.readAsDataURL(blob); }); - await modal.present(); -/* - await modal.present(); */ + } - // var blob = new Blob([pdfString], { type: 'application/pdf' }); + // async openFile(blobUrl:string, filename, fileType) { + // console.log(blobUrl, filename, fileType) + // let pathFile: string; - // console.log('blob blob', blob) + // if (this.platform.is('ios')) { + // pathFile = this.file.documentsDirectory + // } else { + // pathFile = this.file.externalRootDirectory + // } - // this.blobToBase64(blob).then((value) => { - // console.log(value) - // }).catch((error) => { - // console.log(error) - // }) + // let a = await this.fetchBlobFromURL(blobUrl) - // let pathFile = '' - // const fileName = filename - // if (this.platform.is('ios')) { - // pathFile = this.file.documentsDirectory - // } else { - // pathFile = this.file.externalRootDirectory - // } + // console.log({e:await this.convertBlobToDataURL(a)}) + // let removePre = this.removeTextBeforeSlash(await this.convertBlobToDataURL(a),',') - // console.log('file data', pdfString) - // console.log(pathFile) + // Filesystem.writeFile({ + // path: filename, + // data: removePre, + // directory: Directory.Cache, - // let removePre = this.removeTextBeforeSlash(pdfString,',') - // console.log('file data remove ', removePre) + // }).then(dir => { + // console.log('DIR ', dir) + // this.fileOpener + // .open(dir.uri, fileType) + // .then(() => console.log()) + // .catch(e => console.error(e)) + // }) + // .catch(e => console.log('Error writing file', e)) + // } - // await Filesystem.writeFile({ - // path: fileName, - // data: removePre, - // directory: Directory.Cache, - // }).then((dir) => { - // console.log('DIR ', dir) - // this.fileOpener - // .open(dir.uri, type) - // .then(() => console.log()) - // .catch(e => console.error(e)) - // }).catch((error) => { - // console.log('error writing the file', error) - // }); + async openFile(blobUrl:string, filename, fileType) { + + let pathFile = '' + const fileName = filename + const contentFile = await this.fetchBlobFromURL(blobUrl) + if (this.platform.is('ios')) { + pathFile = this.file.documentsDirectory + } else { + pathFile = this.file.cacheDirectory + } + console.log(pathFile) + console.log(contentFile) + this.file + .writeFile(pathFile, fileName, contentFile, { replace: true }) + .then(success => { + this.fileOpener + .open(pathFile + fileName, fileType) + .then(() => console.log('File is opened')) + .catch(e => console.log('Error opening file', e)); + }) + .catch(e => console.log('Error writing file', e)) } removeTextBeforeSlash(inputString, controlString) { diff --git a/src/app/ui/chat/store/model/room.ts b/src/app/ui/chat/store/model/room.ts index d397a59ba..b145d6c82 100644 --- a/src/app/ui/chat/store/model/room.ts +++ b/src/app/ui/chat/store/model/room.ts @@ -1,4 +1,5 @@ import { IRoom, RoomEntitySchema } from "src/app/core/chat/entity/group"; +import { MessageAttachmentSource } from "src/app/core/chat/entity/message"; import { isDocument } from "src/app/utils/document-mimetype"; export class RoomViewModel implements IRoom { @@ -19,12 +20,17 @@ export class RoomViewModel implements IRoom { Object.assign(this, model) this.formatarData() + this.check() + } + + check() { if(this.messages?.[0]?.attachments[0]?.mimeType?.startsWith('image/') ) { this.lastMessageImage = true } else if (this.messages?.[0]?.attachments[0]?.mimeType && isDocument({mimeType: this.messages?.[0]?.attachments[0]?.mimeType})) { this.lastMessageDocument = true + } else if (this.messages?.[0]?.attachments[0]?.source == MessageAttachmentSource.Webtrix) { + this.lastMessageDocument = true } - } formatarData() {