This commit is contained in:
Peter Maquiran
2024-08-13 10:52:35 +01:00
parent 5b31a186c2
commit 251f533a68
53 changed files with 985 additions and 453 deletions
-2
View File
@@ -9,7 +9,6 @@ import { Storage } from '@ionic/storage';
import { register } from 'swiper/element/bundle';
import { DomSanitizer } from '@angular/platform-browser';
import { ScreenOrientation } from "@ionic-native/screen-orientation/ngx";
import { ChatServiceService } from 'src/app/module/chat/chat-service.service'
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
parse: {
dateInput: "YYYY-MMMM-DD HH:mm"
@@ -39,7 +38,6 @@ export class AppComponent {
private storage: Storage,
private sanitizer: DomSanitizer,
private screenOrientation: ScreenOrientation,
private ChatServiceService: ChatServiceService
) {
window["sanitizer"] = this.sanitizer
+26 -10
View File
@@ -2,33 +2,49 @@ import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { err, ok } from 'neverthrow';
/**
* Parameters for taking a picture.
* @typedef {Object} takePictureParams
* @property {number} [quality=90] - The quality of the picture, from 0 to 100.
* @property {CameraResultType} cameraResultType - The result type of the photo, e.g., Base64, URI.
*/
export type takePictureParams = {
quality?: number;
cameraResultType: CameraResultType;
};
type takePictureParams = {
quality?: number
cameraResultType: CameraResultType
}
/**
* Service for handling camera functionality.
* This service provides methods to interact with the device's camera.
*/
@Injectable({
providedIn: 'root'
})
export class CameraService {
/**
* Creates an instance of CameraService.
*/
constructor() { }
/**
* Takes a picture using the device's camera.
* @param {takePictureParams} params - The parameters for taking the picture.
* @param {number} [params.quality=90] - The quality of the picture, from 0 to 100.
* @param {CameraResultType} params.cameraResultType - The result type of the photo.
* @returns {Promise<ok<File> | err<any>>} A promise that resolves with an `ok` result containing the file or an `err` result containing the error.
*/
async takePicture({quality = 90, cameraResultType }: takePictureParams) {
try {
const file = await Camera.getPhoto({
quality: quality,
// allowEditing: true,
resultType: cameraResultType,
source: CameraSource.Camera
});
return ok(file)
return ok(file);
} catch (e) {
return err(e)
return err(e);
}
}
}
@@ -0,0 +1,50 @@
import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { err, ok } from 'neverthrow';
/**
* Parameters for picking a picture.
* @typedef {Object} PickPictureParams
* @property {number} [quality=90] - The quality of the picture, from 0 to 100. Defaults to 90.
* @property {CameraResultType} [cameraResultType=CameraResultType.DataUrl] - The result type of the photo. Defaults to `CameraResultType.DataUrl`.
*/
type PickPictureParams = {
quality?: number;
cameraResultType?: CameraResultType;
};
/**
* Service for handling file picking functionality.
* This service provides methods to pick a picture from the device's photo library.
*/
@Injectable({
providedIn: 'root'
})
export class FilePickerService {
/**
* Creates an instance of FilePickerService.
*/
constructor() { }
/**
* Picks a picture from the device's photo library.
* @param {PickPictureParams} params - The parameters for picking the picture.
* @param {number} [params.quality=90] - The quality of the picture, from 0 to 100. Defaults to 90.
* @param {CameraResultType} [params.cameraResultType=CameraResultType.DataUrl] - The result type of the photo. Defaults to `CameraResultType.DataUrl`.
* @returns {Promise<ok<File> | err<any>>} A promise that resolves with an `ok` result containing the file or an `err` result containing the error.
*/
async getPicture({quality = 90, cameraResultType = CameraResultType.DataUrl }: PickPictureParams) {
try {
const file = await Camera.getPhoto({
quality: quality,
resultType: cameraResultType,
source: CameraSource.Photos
});
return ok(file);
} catch (e) {
return err(e);
}
}
}
@@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
import { FilePicker, PickFilesResult } from '@capawesome/capacitor-file-picker';
import { err, ok, Result } from 'neverthrow';
@Injectable({
providedIn: 'root'
})
export class FilePickerMobileService {
constructor() { }
async getFile({types, multiple, readData}): Promise<Result<PickFilesResult, any>> {
try {
const result = await FilePicker.pickFiles({
types: ['application/pdf', 'application/doc', 'application/docx','application/xls', 'application/xlsx', 'application/ppt',
'application/pptx', 'application/txt'],
multiple: false,
readData: true,
});
return ok(result)
} catch (e) {
return err(e)
}
}
}
@@ -3,10 +3,7 @@ import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { err, ok, Result } from 'neverthrow';
import { FileType } from 'src/app/models/fileType';
type PickPictureParams = {
quality?: number,
cameraResultType?: CameraResultType
}
@Injectable({
providedIn: 'root'
@@ -30,19 +27,4 @@ export class FilePickerWebService {
})
}
async getPicture({quality = 90, cameraResultType =CameraResultType.DataUrl }: PickPictureParams) {
try {
const file = await Camera.getPhoto({
quality: quality,
// allowEditing: true,
resultType: cameraResultType,
source: CameraSource.Photos
});
return ok(file)
} catch (e) {
return err(e)
}
}
}
+11
View File
@@ -0,0 +1,11 @@
export enum StartRecordingResultError {
NoSpeaker,
NeedPermission,
alreadyRecording
}
export enum StopRecordingResultError {
haventStartYet,
NoValue,
UnknownError
}
@@ -1,12 +0,0 @@
import { Injectable } from '@angular/core';
import { UserTypingAsyncService } from 'src/app/module/chat/data/async/socket/user-typing-async.service'
@Injectable({
providedIn: 'root'
})
export class ChatServiceService {
constructor(
private UserTypingAsyncService: UserTypingAsyncService
) { }
}
+4 -1
View File
@@ -1,6 +1,8 @@
import { NgModule } from '@angular/core';
import { SignalRService } from 'src/app/module/chat/infra/socket/signal-r.service'
import { SyncMessageRepositoryService } from './data/service/sync-repository/sync-message-repository.service';
import { UserTypingAsyncService } from 'src/app/module/chat/data/async/socket/user-typing-async.service'
@NgModule({
imports: [
@@ -16,7 +18,8 @@ export class ChatModule {
constructor(
private message: SyncMessageRepositoryService,
private SignalRService: SignalRService
private SignalRService: SignalRService,
private UserTypingAsyncService: UserTypingAsyncService
) {
@@ -1,16 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { MessageRepositoryAyncService } from './message-repository-aync.service';
describe('MessageRepositoryAyncService', () => {
let service: MessageRepositoryAyncService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MessageRepositoryAyncService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -3,10 +3,9 @@ import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MessageRepositoryAyncService {
export class MessageRepositorySyncService {
constructor() {
// alert('hellor')
}
}
@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
import { chatDatabase } from '../../../infra/database/dexie/service';
import { Observable as DexieObservable, PromiseExtended } from 'Dexie';
import { AttachmentTable } from '../../../infra/database/dexie/schema/attachment';
@Injectable({
providedIn: 'root'
})
export class AttachmentLocalDataSourceService extends DexieRepository<AttachmentTable> {
messageSubject = new Subject();
constructor() {
super(chatDatabase.attachment)
}
}
@@ -2,7 +2,6 @@ import { Injectable } from '@angular/core';
import { err, ok } from 'neverthrow';
import { SignalRService } from '../../../infra/socket/signal-r.service';
interface msgObj {
roomId: string;
senderId: string;
@@ -35,4 +34,18 @@ export class MessageLiveDataSourceService {
}
listenToMessages() {
return this.messageLiveSignalRDataSourceService.getMessage()
}
listenToDeleteMessages() {
return this.messageLiveSignalRDataSourceService.getMessageDelete()
}
listenToUpdateMessages() {
return this.messageLiveSignalRDataSourceService.getMessageUpdate()
}
}
@@ -1,13 +1,13 @@
import { Injectable } from '@angular/core';
import { Dexie, EntityTable, liveQuery } from 'Dexie';
import { liveQuery } from 'Dexie';
import { err, ok, Result } from 'neverthrow';
import { from, Observable, Subject } from 'rxjs';
import { Observable, Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { MessageInputDTO } from '../../dto/message/messageInputDtO';
import { MessageEntity } from '../../../domain/entity/message';
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message';
import { chatDatabase } from '../../../infra/database/dexie/service';
import { Observable as DexieObservable, PromiseExtended } from 'Dexie';
@Injectable({
providedIn: 'root'
@@ -61,7 +61,7 @@ export class MessageLocalDataSourceService extends DexieRepository<MessageTable>
}
async sendMessage(data: MessageInputDTO) {
async sendMessage(data: MessageTable) {
(data as MessageTable).sending = true
@@ -76,9 +76,8 @@ export class MessageLocalDataSourceService extends DexieRepository<MessageTable>
}
// @ValidateSchema(tableSchema)
async createMessage(data: MessageInputDTO) {
async createMessage(data: MessageTable) {
try {
const result = await chatDatabase.message.add(data)
@@ -90,7 +89,7 @@ export class MessageLocalDataSourceService extends DexieRepository<MessageTable>
}
async createManyMessage(data: MessageInputDTO[]) {
async createManyMessage(data: MessageTable[]) {
try {
const result = await chatDatabase.message.bulkAdd(data)
@@ -147,12 +146,12 @@ export class MessageLocalDataSourceService extends DexieRepository<MessageTable>
}
}
getItems(roomId: string) {
return chatDatabase.message.where('roomId').equals(roomId).toArray()
getItems(roomId: string): PromiseExtended<MessageEntity[]> {
return chatDatabase.message.where('roomId').equals(roomId).sortBy('$id') as any
}
getItemsLive(roomId: string) {
return liveQuery(() => chatDatabase.message.where('roomId').equals(roomId).sortBy('$id'))
getItemsLive(roomId: string): DexieObservable<MessageEntity[]> {
return liveQuery(() => chatDatabase.message.where('roomId').equals(roomId).sortBy('$id') as any)
}
@@ -0,0 +1,11 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MessageMemoryDataSourceService {
messages: {[roomId: string]: string[]} = {}
constructor() {}
}
@@ -31,4 +31,10 @@ export class MessageRemoteDataSourceService {
return await this.httpService.get(`${this.baseUrl}/Room/${id}/Messages`);
}
@APIReturn(MessageOutPutDTOSchema, 'get/Messages/attachment')
async getAttachment(id: string): DataSourceReturn<MessageOutPutDTO> {
return await this.httpService.get(`${this.baseUrl}/attachment/${id}`);
}
}
@@ -1,13 +1,15 @@
import { Injectable } from '@angular/core';
import { WebSocketMessage, WebSocketService } from '../../../infra/socket/socket';
import { err, ok } from 'neverthrow';
import { SignalRService } from '../../../infra/socket/signal-r.service';
import { AddMemberToRoomInputDTO } from '../../dto/room/addMemberToRoomInputDto';
import { v4 as uuidv4 } from 'uuid'
@Injectable({
providedIn: 'root'
})
export class RoomLiveDataSourceService {
// constructor(private socket: WebSocketService) {}
constructor(
private socket: SignalRService,
) {}
// async getRoomById(data: WebSocketMessage) {
@@ -24,4 +26,19 @@ export class RoomLiveDataSourceService {
// }
async addMemberToRoom(data: AddMemberToRoomInputDTO) {
const result = await this.socket.sendData({
method: 'AddRoomMember',
data: {
requestId: uuidv4(),
roomId: data.id,
members: data.members
}
})
console.log({result})
return result
}
}
@@ -12,9 +12,20 @@ import { TypingTable } from '../../../infra/database/dexie/schema/typing';
})
export class UserTypingLocalDataSourceService {
constructor() { }
constructor() {
this.clear();
}
async clear() {
try {
const result = await chatDatabase.typing.clear()
return ok(result)
} catch (e) {
return err(false)
}
}
async addUserTyping(data: TypingTable) {
data.id = data.chatRoomId + '@' + data.userName
@@ -10,14 +10,15 @@ export const MessageInputDTOSchema = z.object({
oneShot: z.boolean(),
requireUnlock: z.boolean(),
requestId: z.string(),
attachments: z.array(z.object({
attachment: z.object({
fileType: z.nativeEnum(MessageAttachmentFileType),
source: z.nativeEnum(MessageAttachmentSource),
file: z.string(),
fileName: z.string(),
applicationId: z.string(),
docId: z.string()
})).optional()
docId: z.string(),
mimeType: z.string().optional()
}).optional()
});
@@ -24,7 +24,6 @@ export const MessageOutPutDataDTOSchema = z.object({
message: z.string().nullable(),
messageType: z.number(),
sentAt: z.string(),
deliverAt: z.string().datetime().nullable(),
canEdit: z.boolean(),
oneShot: z.boolean(),
requireUnlock: z.boolean(),
@@ -39,10 +38,11 @@ export const MessageOutPutDataDTOSchema = z.object({
attachments: z.array(z.object({
fileType: z.nativeEnum(MessageAttachmentFileType),
source: z.nativeEnum(MessageAttachmentSource),
file: z.string(),
fileName: z.string(),
file: z.string().optional(),
fileName: z.string().optional(),
applicationId: z.string().optional(),
docId: z.string().optional()
docId: z.string().optional(),
id: z.string()
}))
});
@@ -1,7 +1,5 @@
import { Injectable } from '@angular/core';
import { MessageRemoteDataSourceService } from '../data-source/message/message-remote-data-source.service';
import { MessageLiveDataSourceService } from '../data-source/message/message-live-data-source.service';
import { MessageLocalDataSourceService } from '../data-source/message/message-local-data-source.service';
import { SessionStore } from 'src/app/store/session.service';
import { SignalRService } from '../../infra/socket/signal-r.service';
import { v4 as uuidv4 } from 'uuid'
@@ -14,7 +12,10 @@ import { InstanceId } from '../../domain/chat-service.service';
import { MessageMapper } from '../../domain/mapper/messageMapper';
import { MessageOutPutDataDTO } from '../dto/message/messageOutputDTO';
import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message';
import { MessageLocalDataSourceService } from '../data-source/message/message-local-data-source.service';
import { MessageLiveDataSourceService } from '../data-source/message/message-live-signalr-data-source.service';
import { AttachmentLocalDataSourceService } from 'src/app/module/chat/data/data-source/attachment/message-local-data-source.service'
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
@@ -25,7 +26,8 @@ export class MessageRepositoryService {
private messageRemoteDataSourceService: MessageRemoteDataSourceService,
private messageLiveDataSourceService: MessageLiveDataSourceService,
private messageLiveSignalRDataSourceService: SignalRService,
private messageLocalDataSourceService: MessageLocalDataSourceService
private messageLocalDataSourceService: MessageLocalDataSourceService,
private AttachmentLocalDataSourceService: AttachmentLocalDataSourceService
) {}
@@ -37,17 +39,30 @@ export class MessageRepositoryService {
}
async sendMessage(entity: MessageEntity) {
const requestId = InstanceId +'@'+ uuidv4();
async createMessage(entity: MessageEntity) {
//const requestId = InstanceId +'@'+ uuidv4();
const localActionResult = await this.messageLocalDataSourceService.sendMessage(entity)
return localActionResult.map(e => {
entity.$id = e
return entity
})
}
async sendMessage(entity: MessageEntity) {
const messageSubject = new Subject<MessageTable | string>();
const roomId = entity.roomId
entity.sending = true
const localActionResult = await this.messageLocalDataSourceService.sendMessage(entity)
if(localActionResult.isOk()) {
const DTO = MessageMapper.fromDomain(entity, requestId)
const DTO = MessageMapper.fromDomain(entity, entity.requestId)
const sendMessageResult = await this.messageLiveSignalRDataSourceService.sendMessage<MessageOutPutDataDTO>(DTO)
// return this sendMessageResult
if(sendMessageResult.isOk()) {
@@ -62,6 +77,8 @@ export class MessageRepositoryService {
$id : localActionResult.value
}
// console.log('sendMessageResult.value', sendMessageResult.value)
// this.attachment(sendMessageResult.value.attachments[0].id)
return this.messageLocalDataSourceService.update(localActionResult.value, {...clone, sending: false, roomId: entity.roomId})
} else {
await this.messageLocalDataSourceService.update(localActionResult.value, {sending: false, $id: localActionResult.value})
@@ -113,12 +130,14 @@ export class MessageRepositoryService {
if(result.isOk()) {
const { addedItems, changedItems } = messageListDetermineChanges(result.value.data, localResult)
const { addedItems, changedItems, deletedItems } = messageListDetermineChanges(result.value.data, localResult)
console.log({addedItems, changedItems});
for(const message of changedItems) {
let clone: MessageTable = message
clone.roomId = id
await this.messageLocalDataSourceService.findOrUpdate(clone)
this.messageLocalDataSourceService.findOrUpdate(clone)
}
for(const message of addedItems) {
@@ -126,7 +145,14 @@ export class MessageRepositoryService {
clone.roomId = id
}
await this.messageLocalDataSourceService.createManyMessage(addedItems.reverse())
this.messageLocalDataSourceService.createManyMessage(addedItems.reverse())
for(const message of deletedItems) {
this.messageLocalDataSourceService.deleteByMessageId(message.id)
}
}
return result
}
@@ -135,6 +161,10 @@ export class MessageRepositoryService {
return this.messageLocalDataSourceService.getItemsLive(roomId)
}
getItems (roomId: string) {
return this.messageLocalDataSourceService.getItems(roomId)
}
subscribeToNewMessages(roomId: any) {
return this.messageLocalDataSourceService.subscribeToNewMessage(roomId)
}
@@ -147,4 +177,9 @@ export class MessageRepositoryService {
})
}
attachment(roomId: string) {
console.log('attachment')
return this.messageRemoteDataSourceService.getAttachment(roomId)
}
}
@@ -16,6 +16,7 @@ import { MessageLiveDataSourceService } from '../data-source/message/message-liv
import { MemberListUPdateStatusInputDTO } from '../../domain/use-case/socket/member-list-update-status-use-case.service';
import { MemberSetAdminDTO } from '../../domain/use-case/member-admin-use-case.service';
import { MemberListMapper } from '../../domain/mapper/memberLIstMapper';
import { SignalRService } from '../../infra/socket/signal-r.service';
function date(isoDateString) {
@@ -43,8 +44,7 @@ export class RoomRepositoryService {
private roomRemoteDataSourceService: RoomRemoteDataSourceService,
// private roomMemoryDataSourceService: Store<RoomRemoteDataSourceState>,
private roomLocalDataSourceService: RoomLocalDataSourceService,
private roomLiveDataSourceService: RoomLiveDataSourceService,
private messageLiveDataSourceService: MessageLiveDataSourceService,
private roomLiveSignalRDataSourceService: RoomLiveDataSourceService,
) {}
@captureAndReraiseAsync('RoomRepositoryService/list')
@@ -80,13 +80,13 @@ export class RoomRepositoryService {
this.list()
}, timeRemaining)
}
}
} catch (error) {
console.log(error)
}
}
return result
}
@@ -223,9 +223,12 @@ export class RoomRepositoryService {
@captureAndReraiseAsync('RoomRepositoryService/addMemberToRoom')
async addMemberToRoom(data: AddMemberToRoomInputDTO) {
const result = await this.roomRemoteDataSourceService.addMemberToRoom(data)
return result
return this.roomLiveSignalRDataSourceService.addMemberToRoom(data)
// const result = await this.roomRemoteDataSourceService.addMemberToRoom(data)
// return result
}
async updateMemberStatus(data: MemberListUPdateStatusInputDTO) {
@@ -9,10 +9,13 @@ import { SignalRService } from '../infra/socket/signal-r.service';
import { SocketMessageDeleteUseCaseService } from 'src/app/module/chat/domain/use-case/socket/socket-message-delete-use-case.service';
import { SocketMessageUpdateUseCaseService } from 'src/app/module/chat/domain/use-case/socket/socket-message-update-use-case.service';
import { SocketMessageCreateUseCaseService } from 'src/app/module/chat/domain/use-case/socket/socket-message-create-use-case.service';
import { ListenMessageByRoomIdNewUseCase } from 'src/app/module/chat/domain/use-case/listen-message-by-roomId.service';
import { MemberListUpdateStatusUseCaseService } from 'src/app/module/chat/domain/use-case/socket/member-list-update-status-use-case.service';
import { ListenMessageDeleteByRoomIdService } from './use-case/listene-message-delete-by-roomId.service';
import { ListenMessageUpdateByRoomIdUseCase } from './use-case/listen-message-update-by-roomId.service';
import { ListenSendMessageUseCase } from './use-case/listen-send-message.service'
import { filter } from 'rxjs/operators';
import { v4 as uuidv4 } from 'uuid'
import { MessageInputDTO } from '../data/dto/message/messageInputDtO';
import { MessageEntity } from './entity/message';
export const InstanceId = uuidv4();
@@ -33,7 +36,11 @@ export class ChatServiceService {
private SocketMessageCreateUseCaseService: SocketMessageCreateUseCaseService,
private MemberListUpdateStatusUseCaseService: MemberListUpdateStatusUseCaseService,
private MemberAdminUseCaseService: MemberAdminUseCaseService,
private MessageCreateUseCaseService: MessageCreateUseCaseService
private MessageCreateUseCaseService: MessageCreateUseCaseService,
private ListenMessageByRoomIdNewUseCase: ListenMessageByRoomIdNewUseCase,
private ListenMessageDeleteService: ListenMessageDeleteByRoomIdService,
private ListenMessageUpdateByRoomIdUseCase: ListenMessageUpdateByRoomIdUseCase,
private ListenSendMessageUseCase: ListenSendMessageUseCase
) {
this.messageLiveSignalRDataSourceService.getMessageDelete()
.pipe()
@@ -106,9 +113,26 @@ export class ChatServiceService {
return this.MemberAdminUseCaseService.execute(input)
}
sendMessage(input: MessageEntity) {
return this.MessageCreateUseCaseService.execute(input);
}
listenToIncomingMessage(roomId:string) {
return this.ListenMessageByRoomIdNewUseCase.execute({roomId})
}
listenToDeleteMessage(roomId: string) {
return this.ListenMessageDeleteService.execute({roomId})
}
listenToUpdateMessage(roomId: string) {
return this.ListenMessageUpdateByRoomIdUseCase.execute({roomId})
}
listenToSendMessage(roomId: string) {
return this.ListenSendMessageUseCase.execute({roomId})
}
}
+25 -6
View File
@@ -21,11 +21,15 @@ const MessageEntitySchema = z.object({
attachments: z.array(z.object({
fileType: z.nativeEnum(MessageAttachmentFileType),
source: z.nativeEnum(MessageAttachmentSource),
file: z.string().optional(),
fileName: z.string().optional(),
applicationId: z.string().optional(),
docId: z.string().optional()
})),
attachmentsSource: z.array(z.object({
file: z.string(),
fileName: z.string(),
applicationId: z.string(),
docId: z.string()
}))
id: z.string(),
})),
})
type Message = z.infer<typeof MessageEntitySchema>;
@@ -56,8 +60,19 @@ export class MessageEntity implements Message {
file?: string,
fileName: string,
applicationId?: string,
docId?: string
}[]
docId?: string,
mimeType?: string,
description?: string
}[] = []
attachmentsSource: {
id: string,
file: string
}[] = []
reactions = []
requestId: string
constructor() {}
@@ -67,4 +82,8 @@ export class MessageEntity implements Message {
}
}
get hasAttachment() {
return this.attachments.length >= 1
}
}
@@ -18,7 +18,7 @@ export class MessageMapper {
roomId: entity.roomId,
senderId: entity.sender.wxUserId,
requestId: requestId,
attachments: entity.attachments
attachment: entity.attachments[0]
}
}
}
@@ -0,0 +1,24 @@
import { Injectable } from '@angular/core';
import { filter, map } from 'rxjs/operators';
import { InstanceId } from '../chat-service.service';
import { MessageLiveDataSourceService } from 'src/app/module/chat/data/data-source/message/message-live-signalr-data-source.service'
import { MessageEntity } from '../entity/message';
@Injectable({
providedIn: 'root'
})
export class ListenMessageByRoomIdNewUseCase {
constructor(
private MessageLiveDataSourceService: MessageLiveDataSourceService
) { }
execute({roomId}: {roomId: string}) {
return this.MessageLiveDataSourceService.listenToMessages().pipe(
filter((message) => !message?.requestId?.startsWith(InstanceId) && message?.roomId == roomId),
map(message => Object.assign(new MessageEntity(), message))
)
}
}
@@ -0,0 +1,19 @@
import { Injectable } from '@angular/core';
import { filter } from 'rxjs/operators';
import { MessageLiveDataSourceService } from '../../data/data-source/message/message-live-signalr-data-source.service';
@Injectable({
providedIn: 'root'
})
export class ListenMessageUpdateByRoomIdUseCase {
constructor(
private messageLiveSignalRDataSourceService: MessageLiveDataSourceService,
) { }
execute({roomId}) {
return this.messageLiveSignalRDataSourceService.listenToUpdateMessages().pipe(
filter((message) => roomId == message?.roomId )
)
}
}
@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { MessageLiveDataSourceService } from 'src/app/module/chat/data/data-source/message/message-live-signalr-data-source.service'
import { InstanceId } from '../chat-service.service';
import { filter, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ListenSendMessageUseCase {
constructor(
private MessageLiveDataSourceService: MessageLiveDataSourceService
) { }
execute({roomId}: {roomId: string}) {
return this.MessageLiveDataSourceService.listenToMessages().pipe(
filter((message) => message?.requestId?.startsWith(InstanceId) && message?.roomId == roomId),
map(message => message)
)
}
}
@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { SignalRService } from '../../infra/socket/signal-r.service';
import { filter } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ListenMessageDeleteByRoomIdService {
constructor(
private messageLiveSignalRDataSourceService: SignalRService,
) { }
execute({roomId}) {
return this.messageLiveSignalRDataSourceService.getMessageDelete().pipe(
filter((message) => {
console.log({message}, 'delete')
return roomId == message?.roomId
} )
)
}
}
@@ -3,6 +3,8 @@ import { MessageEntity } from '../entity/message';
import { SessionStore } from 'src/app/store/session.service';
import { MessageRepositoryService } from "src/app/module/chat/data/repository/message-respository.service"
import { z } from 'zod';
import { v4 as uuidv4 } from 'uuid'
import { InstanceId } from '../chat-service.service';
const MessageInputUseCaseSchema = z.object({
memberId: z.number(),
@@ -26,6 +28,8 @@ export class MessageCreateUseCaseService {
input.sendAttemp++;
input.requestId = InstanceId +'@'+ uuidv4();
const result = await this.MessageRepositoryService.sendMessage(input)
return result
@@ -0,0 +1,35 @@
import { Injectable } from '@angular/core';
import { MessageEntity } from '../entity/message';
import { SessionStore } from 'src/app/store/session.service';
import { MessageRepositoryService } from "src/app/module/chat/data/repository/message-respository.service"
import { z } from 'zod';
const MessageInputUseCaseSchema = z.object({
memberId: z.number(),
roomId: z.string(),
message: z.string()
})
export type MessageInputUseCase = z.infer< typeof MessageInputUseCaseSchema>
@Injectable({
providedIn: 'root'
})
export class MessageCreateUseCaseService {
constructor(
private MessageRepositoryService: MessageRepositoryService
) { }
async execute(input: MessageEntity) {
const result = await this.MessageRepositoryService.createMessage(input)
if(result.isOk()) {
}
return result
}
}
@@ -1,16 +0,0 @@
import { Injectable } from '@angular/core';
import { SyncMessageRepositoryService } from 'src/app/module/chat/data/service/sync-repository/sync-message-repository.service'
@Injectable({
providedIn: 'root'
})
export class SyncLocalMessageService {
constructor(
private SyncMessageRepositoryService: SyncMessageRepositoryService
) { }
async execute() {
return this.SyncMessageRepositoryService.sendLocalMessages()
}
}
@@ -0,0 +1,13 @@
import { z } from "zod";
import { EntityTable } from 'Dexie';
export const AttachmentTableSchema = z.object({
id: z.string(),
$id: z.string(),
messageId: z.string(),
file: z.string(),
})
export type AttachmentTable = z.infer<typeof AttachmentTableSchema>
export type DexieAttachmentsTableSchema = EntityTable<AttachmentTable, '$id'>;
export const AttachmentTableColumn = '++$id, id, messageId, file'
@@ -1,5 +1,6 @@
import { z } from "zod";
import { nativeEnum, z } from "zod";
import { EntityTable } from 'Dexie';
import { MessageAttachmentFileType, MessageAttachmentSource } from "src/app/module/chat/data/dto/message/messageOutputDTO";
export const MessageTable = z.object({
$id: z.number().optional(),
@@ -25,7 +26,14 @@ export const MessageTable = z.object({
sender: z.object({}),
}).array().optional(),
info: z.array(z.object({})).optional(),
attachments: z.array(z.object({})).optional()
attachments: z.array(z.object({
fileType: z.nativeEnum(MessageAttachmentFileType),
source: z.nativeEnum(MessageAttachmentSource),
file: z.string().optional(),
fileName: z.string().optional(),
applicationId: z.string().optional(),
docId: z.string().optional()
})).optional()
})
export type MessageTable = z.infer<typeof MessageTable>
@@ -5,6 +5,7 @@ import { DexieMembersTableSchema, MemberTableColumn } from './schema/members';
import { DexieRoomsTableSchema, RoomTableColumn } from './schema/room';
import { DexieTypingsTableSchema, TypingTableColumn } from './schema/typing';
import { MessageEntity } from '../../../domain/entity/message';
import { AttachmentTable, AttachmentTableColumn, DexieAttachmentsTableSchema } from './schema/attachment';
// import DexieMemory from 'dexie-in-memory';
// Database declaration (move this to its own module also)
@@ -12,14 +13,16 @@ export const chatDatabase = new Dexie('chat-database-infra') as Dexie & {
message: DexieMessageTable,
members: DexieMembersTableSchema,
room: DexieRoomsTableSchema,
typing: DexieTypingsTableSchema
typing: DexieTypingsTableSchema,
attachment: DexieAttachmentsTableSchema,
};
chatDatabase.version(1).stores({
message: messageTableColumn,
members: MemberTableColumn,
room: RoomTableColumn,
typing: TypingTableColumn
typing: TypingTableColumn,
attachment: AttachmentTableColumn
});
chatDatabase.message.mapToClass(MessageEntity)
@@ -15,12 +15,12 @@ const { App } = Plugins;
const SignalRInputSchema = z.object({
method: z.string(),
data: z.object({
requestId: z.string()
})
requestId: z.string(),
}).catchall(z.unknown()), // Allows any additional properties with unknown values
})
export type ISignalRInput = z.infer<typeof SignalRInputSchema>
export type ISignalRInput = z.infer<typeof SignalRInputSchema>;
@Injectable({
providedIn: 'root'
@@ -92,6 +92,7 @@ export class SignalRService {
})
this.connection.getMessageDelete().subscribe((data) => {
console.log('delete middleware', data)
this.messageDelete.next(data)
})
+1 -1
View File
@@ -306,7 +306,7 @@ export class SignalRConnection {
console.log('DeleteMessage', _message)
this.messageDelete.next(_message);
this.sendDataSubject.next({
method: 'ReceiveMessage',
method: 'DeleteMessage',
data: _message
})
});
@@ -24,7 +24,7 @@
</ion-header>
<ion-content>
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
<ion-refresher-content>
@@ -32,8 +32,8 @@
</ion-refresher>
<div class="main-content">
<ion-progress-bar class="position-absolute" type="indeterminate" *ngIf="loading"></ion-progress-bar>
<ion-virtual-scroll [items]="ChatSystemService.users | filter:textSearch: 'name' " approxItemHeight="70px" [headerFn]="separateLetter">
<!-- <ion-virtual-scroll [items]="ChatSystemService.users | filter:textSearch: 'name' " approxItemHeight="70px" [headerFn]="separateLetter">
<div class="item-divider" *virtualHeader="let header">
<ion-label>{{header}}</ion-label>
</div>
@@ -46,7 +46,7 @@
</div>
</ion-virtual-scroll>
</ion-virtual-scroll> -->
</div>
</ion-content>
+27 -22
View File
@@ -54,14 +54,28 @@
<div class="d-flex justify-content-between">
<div>
{{ message.message }}
</div>
<div>
{{ message.message }}
</div>
<div *ngFor="let attachment of message.attachments">
<div *ngIf="attachment.fileType == 1">
<ion-icon src="assets/icon/webtrix.svg" class="file-icon font-25"></ion-icon>
<ion-label>{{ attachment.fileName}}</ion-label>
<!-- <ion-icon *ngIf="ThemeService.currentTheme == 'default' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="( msg.downloadLoader == true || msg.uploadingFile == true )" class="icon-download" src="assets/gif/theme/{{ThemeService.currentTheme}}/Blocks-loader.svg" slot="end"></ion-icon> -->
</div>
</div>
<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">
<button (click)="messageDelete({messageId: message.id })" class="menuButton">Apagar mensagem</button>
<button (click)="messageDelete(message)" class="menuButton">Apagar mensagem</button>
<button (click)="editMessage(message)" class="menuButton">Editar mensagem</button>
<button (click)="toggleEmojiPicker(message)" class="menuButton">Reagir mensagem</button>
</mat-menu>
@@ -128,7 +142,7 @@
</div>
-->
</div>
</ion-content>
<ion-footer>
@@ -170,26 +184,17 @@
</div>
</div>
<div>
<button #recordbtn *ngIf="!textField && !lastAudioRecorded"
(click)="startRecording()" class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send"
src="assets/icon/theme/default/icons-chat-record-audio.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send"
src="assets/icon/theme/gov/icons-chat-record-audio.svg"></ion-icon>
<button #recordbtn *ngIf="textField == '' && !lastAudioRecorded" (click)="startRecording()" class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/default/icons-chat-record-audio.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-record-audio.svg"></ion-icon>
</button>
<button *ngIf="textField" class="btn-no-color" (click)="sendMessage()"
class="btn-no-color">
<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 *ngIf="textField != ''" class="btn-no-color" (click)="sendMessage()">
<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>
<button *ngIf="!textField && lastAudioRecorded"
(click)="sendAudio(lastAudioRecorded)" class="btn-no-color">
<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 *ngIf="textField == '' && lastAudioRecorded" class="btn-no-color" (click)="sendAudio(lastAudioRecorded)">
<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>
+220 -189
View File
@@ -13,14 +13,11 @@ import { ChatOptionsPopoverPage } from 'src/app/shared/popover/chat-options-popo
import { MessagesOptionsPage } from 'src/app/shared/popover/messages-options/messages-options.page';
import { ChatMessageStore } from 'src/app/store/chat/chat-message.service';
import { ChatUserStorage } from 'src/app/store/chat/chat-user.service';
import { environment } from 'src/environments/environment';
import { ThemeService } from 'src/app/services/theme.service'
import { VoiceRecorder, RecordingData, GenericResponse } from 'capacitor-voice-recorder';
import { Haptics, ImpactStyle } from '@capacitor/haptics';
import { ViewEventPage } from 'src/app/modals/view-event/view-event.page';
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service'
// import { MessageService } from 'src/app/services/chat/message.service';
import { FileType } from 'src/app/models/fileType';
import { SearchPage } from 'src/app/pages/search/search.page';
import { Storage } from '@ionic/storage';
@@ -52,8 +49,12 @@ import { tap } from 'rxjs/operators';
import { MessageEntity } from 'src/app/module/chat/domain/entity/message';
import { MemberTable } from 'src/app/module/chat/infra/database/dexie/schema/members';
import { TypingTable } from 'src/app/module/chat/infra/database/dexie/schema/typing';
import { CameraService } from 'src/app/infra/camera/camera.service'
import { MessageAttachmentFileType, MessageAttachmentSource } from 'src/app/module/chat/data/dto/message/messageOutputDTO';
import { compressImageBase64 } from 'src/app/utils/imageCompressore';
import { FilePickerService } from 'src/app/infra/file-picker/file-picker.service'
import { FilePickerMobileService } from 'src/app/infra/file-picker/mobile/file-picker-mobile.service'
import { AttachmentsPageRoutingModule } from '../../events/attachments/attachments-routing.module';
const IMAGE_DIR = 'stored-images';
@@ -155,7 +156,10 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
private roomRepositoryService: RoomRepositoryService,
private messageRepositoryService: MessageRepositoryService,
private userTypingServiceRepository: UserTypingServiceRepository,
private chatServiceService: ChatServiceService
private chatServiceService: ChatServiceService,
private CameraService: CameraService,
private FilePickerService: FilePickerService,
private FilePickerMobileService: FilePickerMobileService
) {
@@ -439,8 +443,20 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
}
sendMessage() {
// this.ChatSystemService.getDmRoom(this.roomId).send({}).then(() => {
// })
const message = new MessageEntity();
message.message = this.textField
message.roomId = this.roomId
message.sender = {
userPhoto: '',
wxeMail: SessionStore.user.Email,
wxFullName: SessionStore.user.FullName,
wxUserId: SessionStore.user.UserId
}
this.chatServiceService.sendMessage(message)
this.textField = ''
}
/* sendMessage(msg) {
@@ -472,30 +488,26 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
//Converting base64 to blob
const encodedData = btoa(this.audioRecorded);
const blob = this.fileService.base64toBlob(encodedData, recordData.value.mimeType)
const message = new MessageEntity();
message.roomId = this.roomId
const validation = await this.FileValidatorService.validateAudioFromBlob(blob)
message.sender = {
userPhoto: '',
wxeMail: SessionStore.user.Email,
wxFullName: SessionStore.user.FullName,
wxUserId: SessionStore.user.UserId
}
const formData = new FormData();
formData.append("blobFile", blob);
message.attachments = [{
file: encodedData,
fileName: "audio",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Audio
}]
this.chatServiceService.sendMessage(message)
// this.ChatSystemService.getDmRoom(roomId).send({
// file: {
// "type": "application/audio",
// "msDuration": audioFile.value.msDuration,
// "mimeType": audioFile.value.mimeType,
// },
// attachments: [{
// "title": sanitize(fileName),
// "title_link_download": true,
// "type": "audio"
// }],
// temporaryData: formData,
// attachmentsModelData: {
// fileBase64: encodedData,
// }
// })
});
this.deleteRecording();
@@ -689,51 +701,47 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
}
async takePicture() {
async takePictureMobile() {
const roomId = this.roomId
const picture = await this.CameraService.takePicture({
cameraResultType: CameraResultType.DataUrl,
quality: 90
})
const file = await Camera.getPhoto({
quality: 90,
// allowEditing: true,
resultType: CameraResultType.Base64,
source: CameraSource.Camera
});
if(picture.isOk()) {
const file = picture.value
var imageBase64 = 'data:image/jpeg;base64,' + file.base64String
const compressedImage = await compressImageBase64(
file.dataUrl,
800, // maxWidth
800, // maxHeight
0.9 // quality
)
if(compressedImage.isOk()) {
const compressedImage = await this.compressImageBase64(
imageBase64,
800, // maxWidth
800, // maxHeight
0.9 // quality
).then((picture) => {
console.log('Selected: ', picture)
imageBase64 = picture
});
const message = new MessageEntity();
message.roomId = this.roomId
//console.log(imageBase64)
const blob = this.dataURItoBlob(imageBase64)
message.sender = {
userPhoto: '',
wxeMail: SessionStore.user.Email,
wxFullName: SessionStore.user.FullName,
wxUserId: SessionStore.user.UserId
}
const formData = new FormData();
formData.append("blobFile", blob);
message.attachments = [{
file: compressedImage.value,
fileName: "foto",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Image
}]
// this.ChatSystemService.getDmRoom(roomId).send({
// file: {
// "type": "application/img",
// "guid": ''
// },
// attachments: [{
// "title": "file.jpg",
// "text": "description",
// "title_link_download": false,
// }],
// temporaryData: formData,
// attachmentsModelData: {
// fileBase64: imageBase64,
// }
// })
this.chatServiceService.sendMessage(message)
}
}
}
@@ -762,13 +770,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
}
async addImageMobile() {
this.addFileToChatMobile(['image/apng', 'image/jpeg', 'image/png'])
}
async addImage() {
this.addFileToChat(['image/apng', 'image/jpeg', 'image/png'])
}
async addFile() {
this.addFileToChat(['.doc', '.docx', '.pdf'])
@@ -791,85 +792,130 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
if (data.selected) {
// this.ChatSystemService.getDmRoom(roomId).send({
// file: {
// "name": res.data.selected.Assunto,
// "type": "application/webtrix",
// "ApplicationId": res.data.selected.ApplicationType,
// "DocId": res.data.selected.Id,
// "Assunto": res.data.selected.Assunto,
// },
// temporaryData: res,
// attachments: [{
// "title": res.data.selected.Assunto,
// "description": res.data.selected.DocTypeDesc,
// // "title_link": url_no_options,
// "title_link_download": true,
// "thumb_url": "https://static.ichimura.ed.jp/uploads/2017/10/pdf-icon.png",
// // "message_link": url_no_options,
// "text": res.data.selected.DocTypeDesc,
// "type": "webtrix"
// }],
// })
const message = new MessageEntity();
message.message = this.textField
message.roomId = this.roomId
message.sender = {
userPhoto: '',
wxeMail: SessionStore.user.Email,
wxFullName: SessionStore.user.FullName,
wxUserId: SessionStore.user.UserId
}
message.attachments = [{
fileName: res.data.selected.Assunto,
source: MessageAttachmentSource.Webtrix,
fileType: MessageAttachmentFileType.Doc,
applicationId: res.data.selected.ApplicationType,
docId: res.data.selected.Id,
}]
this.chatServiceService.sendMessage(message)
this.textField = ''
}
});
}
async addFileToChatMobile(types: typeof FileType[]) {
const roomId = this.roomId
async pickPicture() {
const file = await Camera.getPhoto({
quality: 90,
// allowEditing: true,
resultType: CameraResultType.Base64,
source: CameraSource.Photos
});
const file = await this.FilePickerService.getPicture({
cameraResultType: CameraResultType.Base64
})
//const imageData = await this.fileToBase64Service.convert(file)
//
if(file.isOk()) {
var imageBase64 = 'data:image/jpeg;base64,' + file.base64String
var base64 = 'data:image/jpeg;base64,' + file.value.base64String
if (file.value.format == "jpeg" || file.value.format == "png" || file.value.format == "gif") {
const compressedImage = await compressImageBase64(
base64,
800, // maxWidth
800, // maxHeight
0.9 // quality
)
const compressedImage = await this.compressImageBase64(
imageBase64,
800, // maxWidth
800, // maxHeight
0.9 // quality
).then((picture) => {
console.log('Selected: ', picture)
imageBase64 = picture
});
if(compressedImage.isOk()) {
//console.log(imageBase64)
const message = new MessageEntity();
message.roomId = this.roomId
const response = await fetch(imageBase64);
const blob = await response.blob();
message.sender = {
userPhoto: '',
wxeMail: SessionStore.user.Email,
wxFullName: SessionStore.user.FullName,
wxUserId: SessionStore.user.UserId
}
const formData = new FormData();
//console.log('add file', formData)
formData.append("blobFile", blob);
//console.log('add file', formData)
message.attachments = [{
file: compressedImage.value,
fileName: "foto",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Image
}]
// this.ChatSystemService.getDmRoom(roomId).send({
// file: {
// "type": "application/img",
// "guid": ''
// },
// temporaryData: formData,
// attachments: [{
// "title": file.path,
// "text": "description",
// "title_link_download": false,
// }],
// attachmentsModelData: {
// fileBase64: imageBase64,
// }
// })
this.chatServiceService.sendMessage(message)
}
}
}
}
// async addFileToChatMobile() {
// const roomId = this.roomId
// const file = await Camera.getPhoto({
// quality: 90,
// // allowEditing: true,
// resultType: CameraResultType.Base64,
// source: CameraSource.Photos
// });
// //const imageData = await this.fileToBase64Service.convert(file)
// //
// var imageBase64 = 'data:image/jpeg;base64,' + file.base64String
// const compressedImage = await this.compressImageBase64(
// imageBase64,
// 800, // maxWidth
// 800, // maxHeight
// 0.9 // quality
// ).then((picture) => {
// console.log('Selected: ', picture)
// imageBase64 = picture
// });
// //console.log(imageBase64)
// const response = await fetch(imageBase64);
// const blob = await response.blob();
// const formData = new FormData();
// //console.log('add file', formData)
// formData.append("blobFile", blob);
// //console.log('add file', formData)
// // this.ChatSystemService.getDmRoom(roomId).send({
// // file: {
// // "type": "application/img",
// // "guid": ''
// // },
// // temporaryData: formData,
// // attachments: [{
// // "title": file.path,
// // "text": "description",
// // "title_link_download": false,
// // }],
// // attachmentsModelData: {
// // fileBase64: imageBase64,
// // }
// // })
// }
getFileReader(): FileReader {
const fileReader = new FileReader();
const zoneOriginalInstance = (fileReader as any)["__zone_symbol__originalInstance"];
@@ -890,7 +936,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
})
}
async addFileToChat(types: typeof FileType[]) {
async addFileToChat(types) {
console.log('add file ')
const roomId = this.roomId
@@ -906,29 +952,25 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
console.log('RESULT', resultt.files[0].data)
const blobb = this.fileService.base64toBlob(resultt.files[0].data, resultt.files[0].mimeType)
const blob = new Blob([resultt.files[0].data], {type: resultt.files[0].mimeType});
const message = new MessageEntity();
message.roomId = this.roomId
const formDataa = new FormData();
formDataa.append('blobFile', blobb);
/* console.log('add file', fileBase64) */
message.sender = {
userPhoto: '',
wxeMail: SessionStore.user.Email,
wxFullName: SessionStore.user.FullName,
wxUserId: SessionStore.user.UserId
}
message.attachments = [{
file: resultt.files[0].data,
fileName: resultt.files[0].name,
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Doc
}]
this.chatServiceService.sendMessage(message)
// this.ChatSystemService.getDmRoom(roomId).send({
// file: {
// "type": resultt.files[0].mimeType,
// "guid": '',
// },
// attachments: [{
// "title": sanitize(resultt.files[0].name),
// "name": sanitize(resultt.files[0].name),
// // "text": "description",
// "title_link_download": false,
// }],
// temporaryData: formDataa,
// attachmentsModelData: {
// fileBase64: '',
// }
// })
return
}
@@ -937,17 +979,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
console.log(file)
/* const encodedData = btoa(JSON.stringify(await this.getBase64(file).catch ((error) => {
console.error(error);
})));
const blob = this.fileService.base64toBlob(encodedData, file.type)
const fileBase64 = await this._getBase64(file)
const formData = new FormData();
formData.append('blobFile', blob);
console.log('add file', fileBase64) */
const fileName = file.name
const validation = this.FileValidatorService.fileNameValidation(fileName)
@@ -962,24 +993,27 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
const formData = new FormData();
formData.append('blobFile', blob);
/* console.log('add file', fileBase64) */
// this.ChatSystemService.getDmRoom(roomId).send({
// file: {
// "type": file.type,
// "guid": '',
// },
// attachments: [{
// "title": sanitize(fileName),
// "name": sanitize(fileName),
// // "text": "description",
// "title_link_download": false,
// }],
// temporaryData: formData,
// attachmentsModelData: {
// fileBase64: encodedData,
// }
// });
const message = new MessageEntity();
message.roomId = this.roomId
message.sender = {
userPhoto: '',
wxeMail: SessionStore.user.Email,
wxFullName: SessionStore.user.FullName,
wxUserId: SessionStore.user.UserId
}
message.attachments = [{
file: encodedData,
fileName: "doc",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Doc
}]
this.chatServiceService.sendMessage(message)
} else {
this.toastService._badRequest("Ficheiro inválido")
}
@@ -1022,11 +1056,11 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.bookMeeting();
}
else if (res['data'] == 'take-picture') {
this.takePicture()
this.takePictureMobile()
}
else if (res['data'] == 'add-picture') {
console.log('add-picture')
this.addImageMobile()
this.pickPicture()
}
else if (res['data'] == 'add-document') {
this.addFile()
@@ -1447,6 +1481,3 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.userTypingServiceRepository.addUserTyping(this.roomId)
}
}
@@ -1,6 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ThemeService } from 'src/app/services/theme.service'
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
@@ -26,7 +25,6 @@ export class GroupContactsPage implements OnInit {
@Output() openGroupMessage:EventEmitter<any> = new EventEmitter<any>();
@Output() openGroupContacts:EventEmitter<any> = new EventEmitter<any>();
currentMembers:UserContacts[];
allChatUsers: UserContacts[] = [];
userContainer: {[key: string]: ( UserContacts & {isChecked: boolean})[] } = {}
@@ -59,13 +57,13 @@ export class GroupContactsPage implements OnInit {
id: this.roomId,
members: this.selectedUsers
})
if(addMembers.isOk()) {
// this.addContacts(this.roomId);
this.openGroupMessage.emit(this.roomId);
this.RoomRepositoryService.getRoomById(this.roomId)
} else if(addMembers.error instanceof HttpRequest) {
this.httpErrorHandle.httpStatusHandle(addMembers.error)
}
// if(addMembers.isOk()) {
// // this.addContacts(this.roomId);
// this.openGroupMessage.emit(this.roomId);
// this.RoomRepositoryService.getRoomById(this.roomId)
// } else if(addMembers.error instanceof HttpRequest) {
// this.httpErrorHandle.httpStatusHandle(addMembers.error)
// }
} else {
this.openGroupMessage.emit(this.roomId);
}
@@ -3,7 +3,7 @@
<div class="main-header">
<div class="header-top">
<div class="middle">
<ion-label class="title">{{ ChatSystemService.getGroupRoom(roomId).name.split('-').join(' ') }}</ion-label>
<!-- <ion-label class="title">{{ ChatSystemService.getGroupRoom(roomId).name.split('-').join(' ') }}</ion-label> -->
</div>
<div class="right">
<!-- <div (click)=" ChatSystemService.getGroupRoom(this.roomId).deleteAll()">delete all</div> -->
@@ -18,11 +18,11 @@
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/icon/icons-user.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/icon/theme/gov/icons-user.svg"></ion-icon>
</div>
<div class="header-bottom-contacts" *ngIf="ChatSystemService.getGroupRoom(roomId)">
<!-- <div class="header-bottom-contacts" *ngIf="ChatSystemService.getGroupRoom(roomId)">
<ion-label class="contacts-list" *ngFor="let member of ChatSystemService.getGroupRoom(roomId).membersExcludeMe; let last = last" >
{{member.name}}<span *ngIf="!last">, </span>
</ion-label>
</div>
</div> -->
</div>
</div>
@@ -42,7 +42,7 @@
<ion-label>A conversa original mantêm-se como chat individual</ion-label>
</div>
<div class="messages-list-item-wrapper container-width-100" *ngFor="let msg of ChatSystemService.getGroupRoom(roomId).messages; let last = last">
<div class="messages-list-item-wrapper container-width-100" *ngFor="let msg of []; let last = last">
<div class="message-item incoming-{{msg.u.username!=sessionStore.user.UserName}} max-width-45" *ngIf="msg.t != 'r' && msg.t != 'ul' && msg.t != 'au' && msg.t != 'ru' && msg.msg !=''" [class.dateLabel]="msg.dateLabel">
<div class="message-item-options d-flex justify-content-end" *ngIf="!msg.dateLabel">
<fa-icon [matMenuTriggerFor]="beforeMenu" icon="chevron-down" class="message-options-icon cursor-pointer"></fa-icon>
@@ -213,7 +213,7 @@
{{last ? scrollToBottom() : ''}}
</div>
<div *ngIf="msg.t == 'au' && msg.msg != sessionStore.user.UserName">
<div *ngFor="let user of ChatSystemService.users">
<div *ngFor="let user of []">
<div *ngIf="msg.msg == user.username" class="info-text-leave">
<ion-label>Adicionou {{user.name}}</ion-label><br />
</div>
@@ -252,15 +252,15 @@
<ion-footer>
<div class="typing" *ngIf="ChatSystemService.getGroupRoom(roomId).otherUserType == true">
<ngx-letters-avatar *ngIf="showAvatar"
<!-- <div class="typing" >
<ngx-letters-avatar *ngIf="showAvatar"
[avatarName]= "ChatSystemService.getGroupRoom(roomId).name"
[width]="30"
[circular]="true"
fontFamily="Roboto"></ngx-letters-avatar>
{{ ChatSystemService.getGroupRoom(roomId).userThatIsTyping }} está a escrever...
</div>
</div> -->
<div class="width-100 pl-20 pr-20">
<span *ngIf="!lastAudioRecorded">{{durationDisplay}}</span>
@@ -298,7 +298,7 @@
<div class="width-100">
<div *ngIf="!recording && !lastAudioRecorded" class="type-message">
<ion-textarea autocomplete="on" autocorrect="on" spellcheck="true" (keyup.enter)="sendMessage()" clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" [(ngModel)]="ChatSystemService.getGroupRoom(roomId).message" (ionChange)="ChatSystemService.getGroupRoom(roomId).sendTyping()"></ion-textarea>
<ion-textarea autocomplete="on" autocorrect="on" spellcheck="true" (keyup.enter)="sendMessage()" clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" ></ion-textarea>
</div>
<div *ngIf="recording" class="d-flex align-items-center justify-content-center">
<button (click)="stopRecording()" class="btn-no-color d-flex align-items-center justify-content-center">
@@ -307,7 +307,7 @@
</div>
</div>
<div class="btn-send">
<!-- <div class="btn-send">
<button #recordbtn *ngIf="!ChatSystemService.getGroupRoom(roomId).message && !lastAudioRecorded" (click)="startRecording()" class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="chat-icon-send" src="assets/icon/theme/default/icons-chat-record-audio.svg"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="chat-icon-send" src="assets/icon/theme/gov/icons-chat-record-audio.svg"></ion-icon>
@@ -320,7 +320,7 @@
<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> -->
</div>
</ion-footer>
@@ -44,14 +44,30 @@
<div class="messages height-100 width-100 d-flex flex-column" #scrollMe >
<div
*ngFor="let message of (roomMessage$ | async)" class="messages-list-item-wrapper"
*ngFor="let message of messages1[roomId]" class="messages-list-item-wrapper"
[ngClass]="{'my-message': message.sender.wxUserId === sessionStore.user.UserId, 'other-message': message.sender.wxUserId !== sessionStore.user.UserId}"
>
<div class="message-container">
<div class="d-flex justify-content-between">
<div>
{{ message.message }}
<div>
{{ message.message }}
</div>
<div *ngFor="let attachment of message.attachment">
<div *ngIf="attachment.fileType == 1">
<ion-icon src="assets/icon/webtrix.svg" class="file-icon font-25"></ion-icon>
<ion-label>{{ attachment.fileName}}</ion-label>
<!-- <ion-icon *ngIf="ThemeService.currentTheme == 'default' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/default/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' && attachment.type != 'webtrix' && !( msg.downloadLoader == true || msg.uploadingFile == true ) " class="icon-download" src="assets/icon/theme/gov/icons-download.svg" slot="end"></ion-icon>
<ion-icon *ngIf="( msg.downloadLoader == true || msg.uploadingFile == true )" class="icon-download" src="assets/gif/theme/{{ThemeService.currentTheme}}/Blocks-loader.svg" slot="end"></ion-icon> -->
</div>
</div>
</div>
<div>
+131 -38
View File
@@ -1,8 +1,6 @@
import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { AnimationController, GestureController, IonRange, ModalController, PopoverController } from '@ionic/angular';
import { ToastService } from 'src/app/services/toast.service';
import { ChatOptionsPopoverPage } from 'src/app/shared/popover/chat-options-popover/chat-options-popover.page';
import { MessagesOptionsPage } from 'src/app/shared/popover/messages-options/messages-options.page';
import { ContactsPage } from '../new-group/contacts/contacts.page';
import { ChatOptionsFeaturesPage } from 'src/app/modals/chat-options-features/chat-options-features.page';
import { ChatMessageStore } from 'src/app/store/chat/chat-message.service';
@@ -12,12 +10,10 @@ import { FileService } from 'src/app/services/functions/file.service';
import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page';
import { ThemeService } from 'src/app/services/theme.service';
import { ViewEventPage } from 'src/app/modals/view-event/view-event.page';
import { Storage } from '@ionic/storage';
import { FileType } from 'src/app/models/fileType';
import { SearchPage } from 'src/app/pages/search/search.page';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { DocumentViewer, DocumentViewerOptions } from '@ionic-native/document-viewer';
import { VoiceRecorder, RecordingData, GenericResponse } from 'capacitor-voice-recorder';
import { CameraResultType } from '@capacitor/camera';
import { RecordingData } from 'capacitor-voice-recorder';
import { Filesystem, Directory } from '@capacitor/filesystem';
import { DomSanitizer } from '@angular/platform-browser';
import { Platform } from '@ionic/angular';
@@ -29,7 +25,7 @@ import { ViewMediaPage } from 'src/app/modals/view-media/view-media.page';
import { PermissionService } from 'src/app/services/permission.service';
import { ChatPopoverPage } from '../../popover/chat-popover/chat-popover.page';
import { Observable as DexieObservable } from 'Dexie';
import { Observable, Subscription } from 'rxjs';
import { Subscription } from 'rxjs';
import { MessageRepositoryService } from 'src/app/module/chat/data/repository/message-respository.service'
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message';
@@ -45,9 +41,10 @@ import { JSFileToBase64 } from 'src/app/utils/ToBase64';
import { CameraService } from 'src/app/infra/camera/camera.service'
import { compressImageBase64 } from '../../../utils/imageCompressore';
import { FilePickerWebService } from 'src/app/infra/file-picker/web/file-picker-web.service'
import { FilePickerService } from 'src/app/infra/file-picker/file-picker.service'
import { allowedDocExtension } from 'src/app/utils/allowedDocExtension';
import { SpeakerService, StartRecordingResultError, StopRecordingResultError } from 'src/app/infra/speaker/speaker.service'
const IMAGE_DIR = 'stored-images';
@Component({
selector: 'app-messages',
templateUrl: './messages.page.html',
@@ -59,7 +56,6 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
@ViewChild('scrollMe') private myScrollContainer: ElementRef;
@ViewChild('message-item') messageContainer: ElementRef;
messages: any;
dm: any;
userPresence = '';
dmUsers: any;
@@ -116,6 +112,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
roomName: any;
isAdmin = true;
roomCountDownDate: string;
audioMimeType = ''
textField = ''
@@ -132,18 +129,24 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
totalMessage = 0
recordData:RecordingData
messages: MessageEntity[] = []
messageReceiveSubject: Subscription
messageDeleteSubject: Subscription
messageUpdateSubject: Subscription
messageSendSubject: Subscription
messages1: {[key: string]: MessageEntity[]} = {}
constructor(
public popoverController: PopoverController,
private modalController: ModalController,
/* private navParams: NavParams, */
private animationController: AnimationController,
private toastService: ToastService,
private timeService: TimeService,
private fileService: FileService,
private gestureController: GestureController,
public ThemeService: ThemeService,
private storage: Storage,
// public RochetChatConnectorService: RochetChatConnectorService,
private sanitiser: DomSanitizer,
private file: File,
private platform: Platform,
@@ -155,6 +158,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
private chatServiceService: ChatServiceService,
private CameraService: CameraService,
private FilePickerWebService: FilePickerWebService,
private FilePickerService: FilePickerService,
private SpeakerService: SpeakerService
) {
// update
@@ -163,9 +167,13 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
ngOnChanges(changes: SimpleChanges): void {
this.roomData$ = this.roomRepositoryService.getItemByIdLive(this.roomId)
this.getMessages()
this.listenToIncomingMessage()
this.listenToDeleteMessage()
this.listenToUpdateMessage();
this.listenToSendMessage()
this.roomMessage$ = this.messageRepositoryService.getItemsLive(this.roomId)
this.roomMembers$ = this.roomRepositoryService.getRoomMemberByIdLive(this.roomId) as any
this.roomStatus$ = this.roomRepositoryService.getRoomStatus(this.roomId)
this.roomRepositoryService.getRoomById(this.roomId)
@@ -179,25 +187,77 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
(this.myInputRef.nativeElement as HTMLDivElement).innerHTML = '::'+ uniqueArray
})
}
this.newMessagesStream?.unsubscribe()
this.newMessagesStream = this.messageRepositoryService.subscribeToNewMessages(this.roomId).subscribe((e) => {
async getMessages() {
this.messages1[this.roomId] = []
setTimeout(() => {
this.scrollToBottomClicked()
}, 200)
const messages = await this.messageRepositoryService.getItems(this.roomId)
this.messages1[this.roomId].unshift(...messages)
}
setTimeout(() => {
this.scrollToBottomClicked()
}, 500)
listenToIncomingMessage() {
this.messageReceiveSubject?.unsubscribe();
this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.roomId).subscribe((message) => {
this.messages1[this.roomId].push(message as MessageEntity)
this.scrollToBottomClicked()
});
}
})
listenToDeleteMessage() {
this.messageDeleteSubject?.unsubscribe();
//this.userTyping$ = this.userTypingMemoryDataSource.select(state => state) as any
this.messageDeleteSubject = this.chatServiceService.listenToDeleteMessage(this.roomId).subscribe((deleteMessage) => {
console.log('delete class', deleteMessage);
// let a = this.userTypingMemoryDataSource.select(state => state).subscribe((e) => {
// this.userTyping$ = e as any
// })
const index = this.messages1[this.roomId].findIndex(e => e?.id === deleteMessage.id); // Use triple equals for comparison
if (index !== -1) { // Check if the item was found
console.log('delete ==')
this.messages1[this.roomId].splice(index, 1);
// console.log('removed index', index);
} else {
// console.log('message not found');
}
});
}
listenToUpdateMessage() {
this.messageUpdateSubject?.unsubscribe();
this.messageUpdateSubject = this.chatServiceService.listenToUpdateMessage(this.roomId).subscribe((updateMessage) => {
console.log('update message', updateMessage);
const index = this.messages1[this.roomId].findIndex(e => e?.id === updateMessage.id); // Use triple equals for comparison
if (index !== -1) { // Check if the item was found
console.log('update ==')
this.messages1[this.roomId][index].message = updateMessage.message
this.messages1[this.roomId][index].reactions = updateMessage.reactions
} else {
// console.log('message not found');
}
});
}
listenToSendMessage() {
this.messageSendSubject?.unsubscribe();
this.messageSendSubject = this.chatServiceService.listenToSendMessage(this.roomId).subscribe((updateMessage) => {
console.log('update message', updateMessage);
const index = this.messages1[this.roomId].findIndex(e => e?.requestId === updateMessage.requestId); // Use triple equals for comparison
if (index !== -1) { // Check if the item was found
console.log('update ==')
this.messages1[this.roomId][index].id = updateMessage.id
} else {
// console.log('message not found');
}
});
}
@@ -409,9 +469,9 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
this.recording = false;
const recordData = stop.value
this.recordData = recordData
this.audioMimeType = recordData.value.mimeType
if (recordData.value.recordDataBase64.includes('data:audio')) {
console.log({recordData})
this.audioRecordedDataUrl = recordData.value.recordDataBase64
this.audioRecordedSafe = this.sanitiser.bypassSecurityTrustResourceUrl(recordData.value.recordDataBase64);
}
@@ -448,11 +508,16 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
file: encodedData,
fileName: "audio",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Audio
fileType: MessageAttachmentFileType.Audio,
mimeType: this.audioMimeType
}]
this.chatServiceService.sendMessage(message)
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.deleteRecording();
}
@@ -490,7 +555,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
await modal.present();
}
sendMessage() {
async sendMessage() {
const message = new MessageEntity();
message.message = this.textField
@@ -503,9 +568,16 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
wxUserId: SessionStore.user.UserId
}
this.chatServiceService.sendMessage(message)
this.textField = ''
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
const data = await this.chatServiceService.sendMessage(message)
console.log({data})
}
@@ -676,9 +748,14 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
file: compressedImage.value,
fileName: "foto",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Image
fileType: MessageAttachmentFileType.Image,
mimeType: picture.value.format
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
}
@@ -729,6 +806,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
docId: res.data.selected.Id,
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
this.textField = ''
@@ -740,7 +821,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
async pickPicture() {
const file = await this.FilePickerWebService.getPicture({
const file = await this.FilePickerService.getPicture({
cameraResultType: CameraResultType.Base64
})
@@ -769,12 +850,19 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
}
message.attachments = [{
file: compressedImage.value,
file: file.value.base64String,
fileName: "foto",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Image
fileType: MessageAttachmentFileType.Image,
mimeType: 'image/'+file.value.format,
description: ''
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
}
}
@@ -821,9 +909,14 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
file: fileBase64.value,
fileName: file.value.name,
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Doc
fileType: MessageAttachmentFileType.Doc,
mimeType: file.value.type
}]
this.messages1[this.roomId].push(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
this.chatServiceService.sendMessage(message)
}