mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 20:47:54 +00:00
set last message
This commit is contained in:
@@ -25,11 +25,11 @@ export const MessageEntityAttachmentSchema = z.object({
|
||||
file: base64Schema.optional(),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.string().optional(),
|
||||
id: z.string().optional(),
|
||||
mimeType: z.string().optional(),
|
||||
docId: z.number().optional(),
|
||||
id: z.string().optional().nullable(),
|
||||
mimeType: z.string().nullable().optional(),
|
||||
safeFile: z.any().optional(),
|
||||
description: z.string().nullable().optional()
|
||||
description: z.string().nullable().optional(),
|
||||
})
|
||||
|
||||
export const MessageEntitySchema = z.object({
|
||||
|
||||
@@ -45,7 +45,7 @@ export const MessageOutPutDataDTOSchema = z.object({
|
||||
file: z.string().optional(),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.string().optional(),
|
||||
docId: z.number().optional(),
|
||||
id: z.string().optional()
|
||||
}))
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@ export const MessageGetAllByRoomIdUseCaseOutputSchema = z.object({
|
||||
file: z.string().optional(),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.string().optional(),
|
||||
docId: z.number().optional(),
|
||||
id: z.string().optional()
|
||||
}))
|
||||
}).array()
|
||||
|
||||
@@ -14,8 +14,8 @@ export const AttachmentTableSchema = z.object({
|
||||
source: z.nativeEnum(MessageAttachmentSource).optional(),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.string().optional(),
|
||||
mimeType: z.string().optional(),
|
||||
docId: z.number().optional(),
|
||||
mimeType: z.string().nullable().optional(),
|
||||
id: z.string().uuid().optional(),
|
||||
description: z.string().optional()
|
||||
})
|
||||
|
||||
@@ -39,10 +39,10 @@ export const MessageTableSchema = z.object({
|
||||
source: z.nativeEnum(MessageAttachmentSource),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.string().optional(),
|
||||
docId: z.number().optional(),
|
||||
id: z.string().optional(),
|
||||
description: z.string().nullable().optional(),
|
||||
mimeType: z.string().optional()
|
||||
mimeType: z.string().nullable().optional()
|
||||
})).optional(),
|
||||
origin: z.enum(['history', 'local', 'incoming']).optional()
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { z } from "zod";
|
||||
import { EntityTable } from 'Dexie';
|
||||
import { RoomType } from "src/app/core/chat/entity/group";
|
||||
import { MessageEntity, MessageEntitySchema } from "src/app/core/chat/entity/message";
|
||||
import { MessageTableSchema } from "./message";
|
||||
|
||||
export const RoomTableSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
@@ -15,7 +16,7 @@ export const RoomTableSchema = z.object({
|
||||
createdAt: z.any(),
|
||||
expirationDate: z.any().nullable(),
|
||||
roomType: z.nativeEnum(RoomType),
|
||||
messages: MessageEntitySchema.array().optional(),
|
||||
messages: MessageTableSchema.array().optional(),
|
||||
bold: z.number().optional()
|
||||
})
|
||||
|
||||
|
||||
@@ -13,6 +13,20 @@ export class RoomLocalRepository extends DexieRepository<RoomTable, RoomTable> 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, obj, transaction) => {
|
||||
|
||||
// if((modifications as Partial<RoomTable>).messages?.[0].attachments?.[0]) {
|
||||
// delete (modifications as Partial<RoomTable>).messages[0].attachments[0].file
|
||||
// }
|
||||
|
||||
// return modifications
|
||||
// });
|
||||
}
|
||||
|
||||
getItemsLive() {
|
||||
|
||||
@@ -39,7 +39,7 @@ export const MessageInputDTOSchema = z.object({
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.number().optional(),
|
||||
mimeType: z.string().optional(),
|
||||
mimeType: z.string().nullable().optional(),
|
||||
description: z.string().optional()
|
||||
}).optional()
|
||||
});
|
||||
@@ -80,7 +80,7 @@ export const MessageCreatePutDataDTOSchema = z.object({
|
||||
file: z.string().optional(),
|
||||
fileName: z.string().optional(),
|
||||
applicationId: z.number().optional(),
|
||||
docId: z.string().optional(),
|
||||
docId: z.number().optional(),
|
||||
id: z.string().optional()
|
||||
}))
|
||||
});
|
||||
@@ -181,6 +181,8 @@ export class MessageCreateUseCaseService {
|
||||
|
||||
if(sendMessageResult.isOk()) {
|
||||
|
||||
message.id = sendMessageResult.value.id
|
||||
|
||||
console.log('sendMessageResult', sendMessageResult.value.id)
|
||||
|
||||
if(sendMessageResult.value.sender == undefined || sendMessageResult.value.sender == null) {
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ export class MessageDeleteLiveUseCaseService {
|
||||
public repository: MessageSocketRepositoryService
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'MessageDeleteLiveUseCaseService', module:'chat', bugPrint: true, waitNThrow: 2000})
|
||||
@XTracerAsync({name:'MessageDeleteLiveUseCaseService', module:'chat', bugPrint: true, waitNThrow: 5000})
|
||||
async execute(data: MessageDeleteInputDTO, tracing?: TracingType) {
|
||||
tracing.log('MessageDeleteLiveUseCaseService payload', {
|
||||
data: data
|
||||
|
||||
@@ -22,8 +22,12 @@ export class RoomSetLastMessageService {
|
||||
this.listenToIncomingMessage()
|
||||
this.listenToOnSendDataToSocket()
|
||||
this.loadHistory()
|
||||
this.listenToUpdateMessage()
|
||||
|
||||
}
|
||||
|
||||
private listenToUpdateMessage() {}
|
||||
|
||||
private listenToIncomingMessage() {
|
||||
return this.messageSocketRepository.listenToMessages().pipe(
|
||||
filter((message) => !message?.requestId?.startsWith(InstanceId)), // get all message not send by me
|
||||
@@ -46,15 +50,24 @@ export class RoomSetLastMessageService {
|
||||
private listenToOnSendDataToSocket() {
|
||||
this.messageSocketRepository.listenToSendMessage().subscribe(async (e) => {
|
||||
|
||||
e.data['sender'] = {
|
||||
const message = Object.assign(new MessageEntity(), e.data)
|
||||
|
||||
message.sender = {
|
||||
userPhoto: '',
|
||||
wxeMail: SessionStore.user.Email,
|
||||
wxFullName: SessionStore.user.FullName,
|
||||
wxUserId: SessionStore.user.UserId
|
||||
}
|
||||
e.data['sentAt'] = new Date().toISOString()
|
||||
message.sentAt = new Date().toISOString()
|
||||
|
||||
if(e.data.attachment?.fileType) {
|
||||
message.attachments = [ e.data.attachment ]
|
||||
} else {
|
||||
message.attachments = []
|
||||
}
|
||||
|
||||
const result = await this.roomLocalRepository.update(e.data.roomId, {
|
||||
messages: [e.data]
|
||||
messages: [message]
|
||||
})
|
||||
|
||||
if(result.isErr()) {
|
||||
@@ -91,7 +104,6 @@ export class RoomSetLastMessageService {
|
||||
const loadHistoryLastMessageDate = new Date(loadHistoryFirstMessage.sentAt).getTime()
|
||||
|
||||
if(loadHistoryLastMessageDate>localLastMessageDate) {
|
||||
console.log('update by load history')
|
||||
await this.roomLocalRepository.update(loadHistoryFirstMessage.roomId, {
|
||||
messages: [loadHistoryFirstMessage]
|
||||
})
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ export class SocketMessageDeleteUseCaseService {
|
||||
const result = await this.messageLocalDataSourceService.update(input.id, { isDeleted: true})
|
||||
|
||||
if(result.isOk()) {
|
||||
|
||||
console.log('deleled', result.value)
|
||||
} else {
|
||||
console.log(result.error)
|
||||
}
|
||||
|
||||
@@ -60,33 +60,58 @@
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' && room.id == idSelected && room.roomType == RoomType.Direct" class="icon" slot="start" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-chat-group-chat-40-hover.svg"></ion-icon>
|
||||
</div>
|
||||
<div
|
||||
(click)="openMessagesPage(room.id)"
|
||||
class="item-content flex-grow-1 cursor-pointer"><!-- (click)="openMessages(dm)" -->
|
||||
<div class="item-title-time">
|
||||
<div class="item-title" [class.item-title-active]="room.id == idSelected">
|
||||
<ion-label >
|
||||
<span >
|
||||
<div >
|
||||
<div class="font-15-em" [class.bold-message]="boldTable?.[room.id]?.bold">
|
||||
{{room.roomName}}
|
||||
</div>
|
||||
</div>
|
||||
(click)="openMessagesPage(room.id)" class="item-content flex-grow-1 cursor-pointer"><!-- (click)="openMessages(dm)" -->
|
||||
<div class="item-title-time">
|
||||
<div class="item-title" [class.item-title-active]="room.id == idSelected">
|
||||
<ion-label >
|
||||
<span >
|
||||
<div >
|
||||
<div class="font-15-em" [class.bold-message]="boldTable?.[room.id]?.bold">
|
||||
{{room.roomName}}
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</ion-label>
|
||||
</div>
|
||||
<div class="item-date font-13-em" [class.item-date-active]="room.id == idSelected">
|
||||
{{ room.displayDate }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-date font-13-em" [class.item-date-active]="room.id == idSelected">
|
||||
<!-- {{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : 'No expiration' }} -->
|
||||
{{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }}
|
||||
</div>
|
||||
<div *ngIf="room?.messages?.[0]?.message" class="item-description d-flex align-items-center" [class.item-description-active]="room.id ==idSelected">
|
||||
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> {{room.messages[0].message}} </div>
|
||||
</ion-label>
|
||||
</div>
|
||||
<div class="item-date font-13-em" [class.item-date-active]="room.id == idSelected">
|
||||
{{ room.displayDate }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-date font-13-em" [class.item-date-active]="room.id == idSelected">
|
||||
<!-- {{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : 'No expiration' }} -->
|
||||
{{ expirationDate[room.id] !== null ? expirationDate[room.id] + ' seconds left' : '' }}
|
||||
</div>
|
||||
<div *ngIf="room?.messages?.length >= 1 && room.messages[0].isDeleted!=true" class="item-description d-flex align-items-center" [class.item-description-active]="room.id ==idSelected">
|
||||
<!-- -->
|
||||
<!-- <div *ngIf="room?.messages?.[0]?.message" class="item-description d-flex align-items-center" [class.item-description-active]="room.id ==idSelected"> -->
|
||||
<!-- <div class="item-message" *ngIf="group.otherUserType == false">{{room?.messages?.[0]?.message.u.name}}: {{room?.messages?.[0]?.message.msg}} </div> -->
|
||||
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> {{room.messages[0].message}} </div>
|
||||
<!-- <div *ngIf="group.otherUserType == true">{{group.userThatIsTyping}} está escrever ...</div> -->
|
||||
|
||||
<div class="item-files add-ellipsis" *ngIf="room.messages[0]?.attachments?.length >= 1">
|
||||
|
||||
<fa-icon *ngIf="room.lastMessageDocument" icon="file-alt" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<fa-icon *ngIf="room?.messages?.[0]?.attachments[0]?.mimeType == 'application/audio'" icon="file-audio" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<span *ngIf="room?.messages?.[0]?.attachments[0]?.mimeType == 'application/audio'" class="item-files-title"> audio </span>
|
||||
<fa-icon *ngIf="room?.messages?.[0]?.attachments[0]?.mimeType == 'application/meeting'" icon="calendar-alt" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<fa-icon *ngIf="room.lastMessageImage" icon="image"></fa-icon>
|
||||
<span class="pl-2 font-13-em add-ellipsis">{{ room.messages[0].attachments[0].description }}</span>
|
||||
</div>
|
||||
|
||||
<!-- <div class="item-files" *ngIf="room.attachments">
|
||||
<div *ngIf="room.value.lastMessage.attachments[0].image_url">
|
||||
<fa-icon icon="image" class="file-icon" [class.set-active-item-font-to-white]="room.id == idSelected"></fa-icon>
|
||||
<span> Fotografia</span>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div *ngIf="room?.messages?.length >= 1 && room.messages[0].isDeleted==true">
|
||||
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> Mensagem foi eliminada </div>
|
||||
</div>
|
||||
<!-- -->
|
||||
|
||||
<!-- <div class="item-message font-13-em add-ellipsis white-space-nowrap" *ngIf="room.otherUserType == false"> {{room.messages[0].message}} </div> -->
|
||||
<!-- <div class="font-13-em" *ngIf="room.otherUserType == true">está escrever ...</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<span *ngIf="roomStatus$ | async as roomStatus"><ion-icon *ngIf="roomStatus" class="online" name="ellipse"></ion-icon></span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button title="Menu" class="btn-no-color" (click)="_openMessagesOptions()" >
|
||||
<button title="Menu" class="btn-no-color" (click)="_openMessagesOptions()" *ngIf="roomType == RoomTypeEnum.Group">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/theme/blue/icons-menu.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-menu.svg">
|
||||
</ion-icon>
|
||||
@@ -52,6 +52,13 @@
|
||||
'other-message': message.messageType == IMessageType.normal && message?.sender?.wxUserId !== SessionStore.user.UserId && !message.ballon
|
||||
}"
|
||||
>
|
||||
<!-- Emoji Picker -->
|
||||
<div *ngIf="selectedMessage === message" class="emoji-picker mr-20" [ngStyle]="{'bottom': '0', 'right': '0'}">
|
||||
<span *ngFor="let emoji of emojis" (click)="addReaction(message, emoji)" class="emoji-icon">
|
||||
{{ emoji }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="message-container rotate-div" *ngIf="message.showMessage">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
@@ -143,12 +150,7 @@
|
||||
<ion-icon *ngIf="messageStatus(message) == 'allViewed'" src="assets/images/check-double-solid -viewed.svg"></ion-icon>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Emoji Picker -->
|
||||
<div *ngIf="selectedMessage === message" class="emoji-picker" [ngStyle]="{'bottom': '0', 'right': '0'}">
|
||||
<span *ngFor="let emoji of emojis" (click)="addReaction(message, emoji)" class="emoji-icon">
|
||||
{{ emoji }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="message-container rotate-div" *ngIf="message.isDeleted == true">
|
||||
Mensagem foi eliminada
|
||||
|
||||
@@ -526,3 +526,22 @@ ion-footer {
|
||||
top: -10px;
|
||||
margin-bottom: -15px;
|
||||
}
|
||||
|
||||
|
||||
.emoji-picker {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.emoji-picker button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.emoji-picker button:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren } from '@angular/core';
|
||||
import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnDestroy, OnInit, Output, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren } from '@angular/core';
|
||||
import { AnimationController, GestureController, IonRange, ModalController, PopoverController } from '@ionic/angular';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { ContactsPage } from '../contacts/contacts.page';
|
||||
@@ -26,7 +26,7 @@ import { RoomLocalRepository } from 'src/app/module/chat/data/repository/room/ro
|
||||
import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member/member-list-local-repository.service'
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
||||
import { EditMessagePage } from 'src/app/ui/chat/modal/edit-message/edit-message.page';
|
||||
import { IMessageType, MessageAttachmentFileType, MessageAttachmentSource, MessageEntity } from 'src/app/core/chat/entity/message';
|
||||
import { IMessageType, MessageAttachmentFileType, MessageAttachmentSource } from 'src/app/core/chat/entity/message';
|
||||
import { JSFileToDataUrl } from 'src/app/utils/ToBase64';
|
||||
import { CameraService } from 'src/app/infra/camera/camera.service'
|
||||
import { FilePickerWebService } from 'src/app/infra/file-picker/web/file-picker-web.service'
|
||||
@@ -134,7 +134,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
totalMessage = 0
|
||||
recordData:RecordingData
|
||||
|
||||
messages: MessageEntity[] = []
|
||||
messages: MessageViewModal[] = []
|
||||
|
||||
messageReceiveSubject: Subscription
|
||||
messageDeleteSubject: Subscription
|
||||
@@ -156,6 +156,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
private port: MessagePort;
|
||||
|
||||
date: {[key: string]: Object} = {}
|
||||
handleClickActive = true
|
||||
|
||||
constructor(
|
||||
public popoverController: PopoverController,
|
||||
@@ -239,7 +240,18 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
this.chatServiceService.getRoomById(this.roomId)
|
||||
}
|
||||
|
||||
messageStatus(message: MessageEntity) {
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
handleClickOutside(event: Event) {
|
||||
if (!this.handleClickActive) return;
|
||||
|
||||
const clickedInside = (event.target as HTMLElement).closest('.mat-menu-content');
|
||||
if (!clickedInside) {
|
||||
this.selectedMessage = null;
|
||||
}
|
||||
}
|
||||
|
||||
messageStatus(message: MessageViewModal) {
|
||||
if(this.allViewed(message)) {
|
||||
return 'allViewed'
|
||||
} else if(this.allReceived(message)) {
|
||||
@@ -250,11 +262,11 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
return 'enviar'
|
||||
}
|
||||
}
|
||||
allReceived(message: MessageEntity) {
|
||||
allReceived(message: MessageViewModal) {
|
||||
return message.info.filter(e => typeof e.deliverAt == 'string').length == this.totalMembers
|
||||
}
|
||||
|
||||
allViewed(message: MessageEntity) {
|
||||
allViewed(message: MessageViewModal) {
|
||||
const totalMembers = this.members.filter((e) => message.sender.wxUserId != e.wxUserId ).length
|
||||
return message.info.filter(e => typeof e.readAt == 'string' && message.sender.wxUserId != e.memberId ).length == totalMembers
|
||||
}
|
||||
@@ -343,7 +355,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
}
|
||||
}
|
||||
|
||||
async onImageLoad(message: MessageEntity, index:number) {
|
||||
async onImageLoad(message: MessageViewModal, index:number) {
|
||||
if(message.attachments[0].fileName == LastMessage.attachments[0].fileName) {
|
||||
|
||||
this.scrollToBottom()
|
||||
@@ -357,7 +369,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
|
||||
async onImageError() {}
|
||||
|
||||
async viewOnce(event: Event, message: MessageEntity, index:number) {
|
||||
async viewOnce(event: Event, message: MessageViewModal, index:number) {
|
||||
const params: ViewOncesImagePageInput = {
|
||||
imageDataUrl: message.attachments[index].safeFile as any,
|
||||
}
|
||||
@@ -445,8 +457,17 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
this.messageDeleteSubject = this.chatServiceService.listenToDeleteMessage(this.roomId).subscribe((deleteMessage) => {
|
||||
console.log('delete class', deleteMessage);
|
||||
|
||||
const index = this.messages1[this.roomId].findIndex(e => e?.id === deleteMessage.id); // Use triple equals for comparison
|
||||
this.messages1[this.roomId][index].delete()
|
||||
const index = this.messages1[this.roomId].findIndex(e =>
|
||||
typeof e?.id == 'string' && e?.id === deleteMessage.id ||
|
||||
typeof e?.requestId == 'string' && e?.requestId == deleteMessage.requestId);
|
||||
|
||||
try {
|
||||
console.log(this.messages1[this.roomId][index])
|
||||
this.messages1[this.roomId][index].delete()
|
||||
} catch (e) {
|
||||
console.log('delete', e)
|
||||
}
|
||||
|
||||
// if (index !== -1) { // Check if the item was found
|
||||
// console.log('delete ==')
|
||||
// this.messages1[this.roomId].splice(index, 1);
|
||||
@@ -503,7 +524,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
|
||||
onDisConnect() {}
|
||||
|
||||
toggleEmojiPicker(message: MessageEntity) {
|
||||
toggleEmojiPicker(message: MessageViewModal) {
|
||||
if (this.selectedMessage === message) {
|
||||
this.selectedMessage = null; // Close the picker if it's already open
|
||||
} else {
|
||||
@@ -511,7 +532,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
}
|
||||
}
|
||||
|
||||
addReaction(message: MessageEntity, emoji: string) {
|
||||
addReaction(message: MessageViewModal, emoji: string) {
|
||||
// Logic to add reaction to the message
|
||||
console.log(`Reacting to message ${message.id} with emoji ${emoji.codePointAt(0).toString(16)}`);
|
||||
this.selectedMessage = null; // Close the picker after adding reaction
|
||||
@@ -537,11 +558,11 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
this.UserTypingRemoteRepositoryService.sendTyping(this.roomId)
|
||||
}
|
||||
|
||||
async editMessage(message: MessageEntity) {
|
||||
async editMessage(message: MessageViewModal) {
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
const modal = await this.popoverController.create({
|
||||
component: EditMessagePage,
|
||||
cssClass: '',
|
||||
cssClass: 'edit-message',
|
||||
componentProps: {
|
||||
message: message.message,
|
||||
roomId: this.roomId,
|
||||
@@ -632,6 +653,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
}
|
||||
ngOnDestroy() {
|
||||
window.removeEventListener('scroll', this.scrollChangeCallback, true);
|
||||
this.handleClickActive = false; // Disable the listener before component destruction
|
||||
}
|
||||
|
||||
onContentScrolled(e) {
|
||||
@@ -1188,7 +1210,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
}
|
||||
|
||||
|
||||
messageDelete(message: MessageEntity) {
|
||||
messageDelete(message: MessageViewModal) {
|
||||
// this.messageRepositoryService.sendMessageDelete()
|
||||
this.chatServiceService.messageDelete({
|
||||
messageId: message.id,
|
||||
@@ -1228,7 +1250,8 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
fileName: file.value.name,
|
||||
source: MessageAttachmentSource.Device,
|
||||
fileType: MessageAttachmentFileType.Doc,
|
||||
mimeType: file.value.type
|
||||
mimeType: file.value.type,
|
||||
description: file.value.name
|
||||
}]
|
||||
|
||||
const date = whatsappDate(message.sentAt, false)
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
<div class="main-header">
|
||||
<div class="title-content width-100">
|
||||
<div class="back-icon">
|
||||
<!-- <ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/Theme/doneIt/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<button class="btn-no-color cursor-pointer" >
|
||||
<button class="btn-no-color cursor-pointer" (click)="dismiss()" >
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||
</button> -->
|
||||
</button>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<ion-label class="title">Editar Mensagem</ion-label>
|
||||
@@ -18,34 +17,33 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<div class="main-content">
|
||||
|
||||
<div class="old-message-container d-flex justify-center">
|
||||
<div class="old-message" style="white-space: pre-line;">{{ oldMessage }}</div>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
|
||||
|
||||
<div class="type-message mt-40-em">
|
||||
<ion-textarea #messageInput clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" [(ngModel)]="message" (keyup.enter)="save()" ></ion-textarea>
|
||||
</div>
|
||||
<div class="old-message-container d-flex justify-center">
|
||||
<div class="old-message" style="white-space: pre-line;">{{ oldMessage }}</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
<ion-footer class="ion-no-border">
|
||||
<ion-toolbar class="footer-toolbar px-20">
|
||||
<ion-buttons slot="start">
|
||||
<button class="btn-ok" fill="clear" color="#fff" (click)="save()">
|
||||
<ion-label>Enviar</ion-label>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
<ion-buttons slot="end">
|
||||
<button class="btn-cancel" fill="clear" color="#061b52" (click)="dismiss()" >
|
||||
<ion-label>Cancelar</ion-label>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
|
||||
|
||||
<div class="d-flex align-center mt-40-em mb-40-em mr-20">
|
||||
<div class="type-message flex-1 ml-30 mr-20">
|
||||
<ion-textarea
|
||||
#messageInput
|
||||
placeholder="Escrever uma mensagem"
|
||||
class="message-input "
|
||||
rows="1"
|
||||
autoGrow="true"
|
||||
[(ngModel)]="message"
|
||||
(keyup.enter)="save()"
|
||||
clearOnEdit="false"
|
||||
></ion-textarea>
|
||||
</div>
|
||||
<button class="btn-no-color" (click)="save()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-send.svg"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -64,14 +64,13 @@
|
||||
overflow:auto;
|
||||
padding: 0 0 0 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.type-message {
|
||||
.type-message {
|
||||
display: flex;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 25px;
|
||||
margin: 0 30px 0 30px;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
}
|
||||
@@ -88,7 +87,3 @@
|
||||
display: inline;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
:host {
|
||||
height: 400px;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { ModalController, PopoverController } from '@ionic/angular';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
|
||||
@Component({
|
||||
@@ -16,7 +16,7 @@ export class EditMessagePage implements OnInit {
|
||||
oldMessage: string
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
public popoverController: PopoverController,
|
||||
public ThemeService: ThemeService,
|
||||
) {}
|
||||
|
||||
@@ -29,13 +29,11 @@ export class EditMessagePage implements OnInit {
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
this.modalController.dismiss();
|
||||
this.popoverController.dismiss();
|
||||
}
|
||||
|
||||
save() {
|
||||
// Implement your save logic here
|
||||
console.log('Updated Message:', this.message);
|
||||
this.modalController.dismiss({
|
||||
this.popoverController.dismiss({
|
||||
'message': this.message
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,6 +60,13 @@
|
||||
}"
|
||||
>
|
||||
|
||||
<!-- Emoji Picker -->
|
||||
<div *ngIf="selectedMessage === message" class="emoji-picker mr-20" [ngStyle]="{'bottom': '0', 'right': '0'}">
|
||||
<span *ngFor="let emoji of emojis" (click)="addReaction(message, emoji)" class="emoji-icon">
|
||||
{{ emoji }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="message-container rotate-div" *ngIf="message.showMessage">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
@@ -132,7 +139,7 @@
|
||||
<div>
|
||||
<div class="message-item-options d-flex justify-content-end">
|
||||
<fa-icon [matMenuTriggerFor]="beforeMenu" icon="chevron-down" class="message-options-icon cursor-pointer"></fa-icon>
|
||||
<mat-menu #beforeMenu="matMenu" xPosition="before">
|
||||
<mat-menu class="custom-menu" #beforeMenu="matMenu" xPosition="before">
|
||||
<button (click)="messageDelete(message)" class="menuButton">Apagar mensagem</button>
|
||||
<button *ngIf="!message.hasAttachment" (click)="editMessage(message)" class="menuButton">Editar mensagem</button>
|
||||
<button (click)="toggleEmojiPicker(message)" class="menuButton">Reagir mensagem</button>
|
||||
@@ -151,12 +158,6 @@
|
||||
<ion-icon *ngIf="messageStatus(message) == 'allViewed'" src="assets/images/check-double-solid -viewed.svg"></ion-icon>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Emoji Picker -->
|
||||
<div *ngIf="selectedMessage === message" class="emoji-picker" [ngStyle]="{'bottom': '0', 'right': '0'}">
|
||||
<span *ngFor="let emoji of emojis" (click)="addReaction(message, emoji)" class="emoji-icon">
|
||||
{{ emoji }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message-container rotate-div" *ngIf="message.isDeleted == true">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { AfterViewInit, Component, ElementRef, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { GestureController, ModalController, NavParams, PopoverController, Platform } from '@ionic/angular';
|
||||
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
|
||||
import { ExpedientTaskModalPageNavParamsTask } from 'src/app/models/ExpedientTaskModalPage';
|
||||
@@ -144,7 +144,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
isAdmin = true
|
||||
RoomTypeEnum = RoomType
|
||||
IMessageType = IMessageType
|
||||
|
||||
handleClickActive = true
|
||||
|
||||
constructor(
|
||||
public popoverController: PopoverController,
|
||||
@@ -219,6 +219,17 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
this.chatServiceService.getRoomById(this.roomId)
|
||||
}
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
handleClickOutside(event: Event) {
|
||||
if (!this.handleClickActive) return;
|
||||
|
||||
const clickedInside = (event.target as HTMLElement).closest('.mat-menu-content');
|
||||
if (!clickedInside) {
|
||||
this.selectedMessage = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async getMessages() {
|
||||
|
||||
|
||||
@@ -660,6 +671,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
ngOnDestroy() {
|
||||
window.removeEventListener('scroll', this.scrollChangeCallback, true);
|
||||
this.handleClickActive = false; // Disable the listener before component destruction
|
||||
}
|
||||
|
||||
async sendMessage() {
|
||||
@@ -901,7 +913,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
this.messages1[this.roomId].splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async takePictureMobile() {
|
||||
|
||||
@@ -1131,7 +1143,8 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
file: result.value.files[0].data,
|
||||
fileName: result.value.files[0].name,
|
||||
source: MessageAttachmentSource.Device,
|
||||
fileType: MessageAttachmentFileType.Doc
|
||||
fileType: MessageAttachmentFileType.Doc,
|
||||
description: result.value.files[0].name
|
||||
}]
|
||||
|
||||
this.messages1[this.roomId].push(message)
|
||||
@@ -1425,9 +1438,9 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
async editMessage(message: any) {
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
const modal = await this.popoverController.create({
|
||||
component: EditMessagePage,
|
||||
cssClass: '',
|
||||
cssClass: 'edit-message',
|
||||
componentProps: {
|
||||
message: message.message,
|
||||
roomId: this.roomId,
|
||||
@@ -1448,11 +1461,11 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
toggleEmojiPicker(message: any) {
|
||||
toggleEmojiPicker(message: MessageViewModal) {
|
||||
if (this.selectedMessage === message) {
|
||||
this.selectedMessage = null; // Close the picker if it's already open
|
||||
} else {
|
||||
this.selectedMessage = message; // Open the picker for the selected message
|
||||
this.selectedMessage = message; // Open the picker for the selected message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { IRoom, RoomEntitySchema } from "src/app/core/chat/entity/group";
|
||||
import { isDocument } from "src/app/utils/document-mimetype";
|
||||
|
||||
export class RoomViewModel implements IRoom {
|
||||
|
||||
@@ -11,10 +12,19 @@ export class RoomViewModel implements IRoom {
|
||||
members: typeof RoomEntitySchema._input.members
|
||||
messages: typeof RoomEntitySchema._input.messages
|
||||
displayDate = ''
|
||||
lastMessageImage = false
|
||||
lastMessageDocument = false
|
||||
|
||||
constructor(model: IRoom) {
|
||||
Object.assign(this, model)
|
||||
this.formatarData()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
formatarData() {
|
||||
@@ -53,8 +63,8 @@ export class RoomViewModel implements IRoom {
|
||||
// Se a mensagem foi enviada antes desta semana
|
||||
this.displayDate = dataMensagem.toLocaleDateString("pt-BR"); // Formato: DD/MM/AAAA
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
export function isDocument({mimeType}) {
|
||||
const documentMimeTypes = [
|
||||
'application/pdf',
|
||||
'application/msword',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.ms-powerpoint',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'text/plain'
|
||||
];
|
||||
|
||||
return documentMimeTypes.includes(mimeType);
|
||||
}
|
||||
Reference in New Issue
Block a user