add contact page

This commit is contained in:
Peter Maquiran
2024-08-16 17:17:32 +01:00
parent 6072a2456b
commit 9d441a3e5b
10 changed files with 241 additions and 252 deletions
@@ -14,8 +14,8 @@ export class AttachmentRemoteDataSourceService {
private httpService: HttpService
) { }
async getAttachment(Input: MessageAttachmentByMessageIdInput): DataSourceReturn<Blob> {
return await this.httpService.get(`${this.baseUrl}/attachment/${Input.id}`, { responseType: 'blob' });
async getAttachment(id: string | number): DataSourceReturn<Blob> {
return await this.httpService.get(`${this.baseUrl}/attachment/${id}`, { responseType: 'blob' });
}
}
@@ -9,6 +9,7 @@ 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 { DownloadMessageAttachmentUserCaseService } from 'src/app/module/chat/domain/use-case/download-message-attachment-user-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';
@@ -44,7 +45,8 @@ export class ChatServiceService {
private ListenMessageUpdateByRoomIdUseCase: ListenMessageUpdateByRoomIdUseCase,
private ListenSendMessageUseCase: ListenSendMessageUseCase,
private MessageAttachmentByMessageIdService: MessageAttachmentByMessageIdUseCase,
private SyncAllRoomMessagesService: SyncAllRoomMessagesService
private SyncAllRoomMessagesService: SyncAllRoomMessagesService,
private DownloadMessageAttachmentUserCaseService: DownloadMessageAttachmentUserCaseService
) {
this.messageLiveSignalRDataSourceService.getMessageDelete()
.pipe()
@@ -129,6 +131,11 @@ export class ChatServiceService {
return this.MessageAttachmentByMessageIdService.execute(input)
}
downloadMessageAttachmentByMessageId(input: MessageAttachmentByMessageIdInput) {
return this.DownloadMessageAttachmentUserCaseService.execute(input)
}
listenToIncomingMessage(roomId:string) {
return this.ListenMessageByRoomIdNewUseCase.execute({roomId})
}
@@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';
import { AttachmentRemoteDataSourceService } from 'src/app/module/chat/data/data-source/attachment/attachment-remote-data-source.service'
import { Logger } from 'src/app/services/logger/main/service';
import { convertBlobToDataURL } from 'src/app/utils/ToBase64';
import { AttachmentLocalDataSource } from 'src/app/module/chat/data/data-source/attachment/attachment-local-data-source.service'
import { MessageAttachmentByMessageIdInput } from './message-attachment-by-message-id.service';
@Injectable({
providedIn: 'root'
})
export class DownloadMessageAttachmentUserCaseService {
constructor(
private AttachmentRemoteDataSourceService: AttachmentRemoteDataSourceService,
private AttachmentLocalDataSource: AttachmentLocalDataSource
) { }
async execute(input: MessageAttachmentByMessageIdInput) {
const result = await this.AttachmentRemoteDataSourceService.getAttachment(input.$messageId)
return result.asyncMap(async (e) => {
const dataUrl = await convertBlobToDataURL(e)
Logger.info('downloaded file #1', {
data: dataUrl.slice(0, 100)+'...',
context: 'DownloadMessageAttachmentUserCaseService'
})
this.AttachmentLocalDataSource.insert({
$messageId: input.$messageId,
id: input.id,
file: dataUrl
})
return dataUrl
})
}
}
@@ -4,6 +4,7 @@ import { AttachmentRemoteDataSourceService } from 'src/app/module/chat/data/data
import { AttachmentLocalDataSource } from 'src/app/module/chat/data/data-source/attachment/attachment-local-data-source.service'
import { convertBlobToDataURL } from 'src/app/utils/ToBase64';
import { Result } from 'neverthrow';
import { Logger } from 'src/app/services/logger/main/service';
const MessageAttachmentByMessageIdSchema = z.object({
$messageId: z.number(),
@@ -33,10 +34,13 @@ export class MessageAttachmentByMessageIdUseCase {
return getLocalAttachment.map(e => e.file)
}
} else {
const result = await this.AttachmentRemoteDataSourceService.getAttachment(input)
const result = await this.AttachmentRemoteDataSourceService.getAttachment(input.id)
return result.asyncMap(async (e) => {
const dataUrl = await convertBlobToDataURL(e)
Logger.info('downloaded file', {
data: dataUrl.slice(0, 100)+'...'
})
this.AttachmentLocalDataSource.insert({
$messageId: input.$messageId,
+8 -2
View File
@@ -39,7 +39,10 @@ export class Logger {
console.info(
`[${getCurrentTime()}] %cINFO : `, // Console Message
'color: #039BE5', // CSS Style
Object.assign(obj, { createdAt: getCurrentTime(), message })
message+' '+
'\n',
obj,
'\n',
);
}
@@ -47,7 +50,10 @@ export class Logger {
console.warn(
`[${getCurrentTime()}] %cWARN : `, // Console Message
'color: #FB8C00', // CSS Style
Object.assign(obj, { createdAt: getCurrentTime(), message })
message+' '+
'\n',
obj,
'\n',
);
}
@@ -29,6 +29,7 @@
</ion-refresher>
<div class="main-content">
------
<ion-progress-bar class="position-absolute" type="indeterminate" *ngIf="loading"></ion-progress-bar>
<ion-virtual-scroll [items]="userList" approxItemHeight="70px" [headerFn]="separateLetter">
@@ -251,7 +251,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
if(message.hasAttachment) {
const result = await this.chatServiceService.getMessageAttachmentByMessageId({
const result = await this.chatServiceService.downloadMessageAttachmentByMessageId({
$messageId: message.$id,
id: message.attachments[0].id
})
@@ -26,27 +26,23 @@
<ion-content>
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
<ion-progress-bar type="indeterminate" *ngIf="loading"></ion-progress-bar>
<ion-refresher-content>
</ion-refresher-content>
</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">
<div *ngFor="let userContainer of userContainer | keyvalue;" >
<div class="item-divider" *virtualHeader="let header">
<ion-label>{{header}}</ion-label>
<div class="item-divider">
<ion-label>{{ userContainer.key }}</ion-label>
</div>
<div (click)="createRoom(user.username)" *virtualItem="let user" class="item-user cursor-pointer">
<p>{{user.name}}</p>
<span class="icon">
<ion-icon class="{{user.status}}" slot="end" name="ellipse"></ion-icon>
</span>
<div *ngFor="let user of userContainer.value; let i = index" class="d-flex px-20 align-center">
<ion-label class="flex-grow-1 px-10">{{user.wxFullName}}</ion-label>
<div class="icon"><ion-icon name="ellipse"></ion-icon></div>
</div>
</ion-virtual-scroll> -->
</div>
</div>
</ion-content>
@@ -1,12 +1,16 @@
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { AuthService } from 'src/app/services/auth.service';
import { ChatService } from 'src/app/services/chat.service';
import { MessagesPage } from '../messages.page';
import { ThemeService } from 'src/app/services/theme.service'
// import { ChatSystemService} from 'src/app/services/chat/chat-system.service'
import { SessionStore } from 'src/app/store/session.service';
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { ToastService } from 'src/app/services/toast.service';
import { HttpRequest, HttpResponse } from '@angular/common/http';
import { ZodError } from 'zod';
@Component({
selector: 'app-contacts',
@@ -14,7 +18,7 @@ import { SessionStore } from 'src/app/store/session.service';
styleUrls: ['./contacts.page.scss'],
})
export class ContactsPage implements OnInit {
showLoader: boolean;
loading: boolean;
loggedUser: any;
users = [];
@@ -23,15 +27,23 @@ export class ContactsPage implements OnInit {
room:any;
dm:any;
sessionStore = SessionStore
userList = []
userList: UserContacts[] = []
currentMembers:UserContacts[];
allChatUsers: UserContacts[] = [];
userContainer: {[key: string]: ( UserContacts & {isChecked: boolean})[] } = {}
selectedUsers: number[] =[]
SessionStore = SessionStore
constructor(
private modalController: ModalController,
private http: HttpClient,
private chatService: ChatService,
private authService: AuthService,
public ThemeService: ThemeService,
// public ChatSystemService: ChatSystemService,
private contactsRepositoryService: ContactRepositoryService,
private RoomRepositoryService: RoomRepositoryService,
private httpErrorHandle: HttpErrorHandle,
private toastService: ToastService,
)
{
this.loggedUser = SessionStore.user.ChatData['data'];
@@ -41,94 +53,116 @@ export class ContactsPage implements OnInit {
this.room=null;
}
ngOnInit() {
// this.chatService.refreshtoken();
// this.loadUsers();
// this.ChatSystemService.getUser()
ngOnInit(): void {
this.loadUsers()
}
get hasMemberToUpload() {
return this.selectedUsers.length >= 1
}
async updateGroup() {
}
openGroupMessagesPage() {
// this.openGroupMessage.emit(this.roomId)
}
async loadUsers() {
this.loading = true
const getallChatUsers = await this.contactsRepositoryService.getUsers()
if(getallChatUsers.isOk()) {
this.allChatUsers = getallChatUsers.value.data.result.sort((a,b) => {
if(a.wxFullName < b.wxFullName) {
return -1;
}
if(a.wxFullName > b.wxFullName) {
return 1;
}
return 0;
});
for(const user of this.allChatUsers) {
const firstLetter = user.wxFullName.charAt(0)
if(!this.userContainer[firstLetter]) {
user['isChecked'] = false
this.userContainer[firstLetter] = [user as any]
} else {
const userIds = this.userContainer[firstLetter].map( e => e.wxUserId)
if(!userIds.includes(user.wxUserId)) {
user['isChecked'] = false
this.userContainer[firstLetter].push(user as any)
}
}
}
}
else if (getallChatUsers.isErr() ) {
console.log(getallChatUsers.error)
} else {
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
}
this.loading = false;
}
doRefresh(ev) {
ev.target.complete();
}
FilterUserListedByTextSearch() {
return this.allChatUsers.filter( e => e.wxFullName.toLowerCase().includes(this.textSearch.toLowerCase())).sort((a,b) => {
if(a.wxFullName < b.wxFullName) {
return -1;
}
if(a.wxFullName > b.wxFullName) {
return 1;
}
return 0;
});
}
onChangeCheckBox(user: UserContacts & {isChecked: boolean}) {
if(user.isChecked) {
this.selectedUsers.push(user.wxUserId)
} else {
this.selectedUsers = this.selectedUsers.filter(e => e!= user.wxUserId)
}
}
onChange(event) {
this.textSearch = event.detail.value;
this.textSearch = event.detail.value.toLowerCase();
const filteredUserList: (UserContacts & {isChecked: boolean})[] = this.FilterUserListedByTextSearch() as any
// this.userList = this.ChatSystemService.users.filter((e) => {
// const username = e.name.toLowerCase()
// return username.includes(this.textSearch)
// })
const userContainer = {}
for(const user of filteredUserList) {
const firstLetter = user.wxFullName.charAt(0)
}
if(!userContainer[firstLetter]) {
user.isChecked = this.selectedUsers.includes(user.wxUserId)
userContainer[firstLetter] = [user]
} else {
user.isChecked = this.selectedUsers.includes(user.wxUserId)
userContainer[firstLetter].push(user)
}
separateLetter(record, recordIndex, records){
if(recordIndex == 0){
return record.name[0];
}
let first_prev = records[recordIndex - 1].name[0];
let first_current = record.name[0];
if(first_prev != first_current){
return first_current;
}
return null;
this.userContainer = userContainer
}
doRefresh(event){
}
close() {
this.modalController.dismiss({});
}
clicked() {}
loading = false
createRoom(username:string) {
if(this.loading) {
return
}
this.loading = true
let body = {
username: username,
}
this.chatService.createRoom(body).subscribe(async(res) => {
this.room = res['room'];
// this.ChatSystemService.getAllRooms(() => {
// this.getDirectMessage(this.room._id);
// this.loading = false
// }, this.room._id);
}, ()=> {
this.loading = false
});
}
getDirectMessage(roomId:any) {
this.openModal(roomId);
}
async openModal(roomId:any){
this.close();
console.log('open chat')
const modal = await this.modalController.create({
component: MessagesPage,
cssClass: 'group-messages',
componentProps: {
roomId: roomId,
},
});
modal.onDidDismiss();
await modal.present();
}
}
+53 -150
View File
@@ -19,7 +19,7 @@ import { Haptics, ImpactStyle } from '@capacitor/haptics';
import { ViewEventPage } from 'src/app/modals/view-event/view-event.page';
import { SearchPage } from 'src/app/pages/search/search.page';
import { Storage } from '@ionic/storage';
import { Camera, CameraResultType } from '@capacitor/camera';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { DomSanitizer } from '@angular/platform-browser';
import { SessionStore } from 'src/app/store/session.service';
import { ViewMediaPage } from 'src/app/modals/view-media/view-media.page';
@@ -147,24 +147,16 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
private gestureController: GestureController,
public ThemeService: ThemeService,
private platform: Platform,
// public ChatSystemService: ChatSystemService,
private storage: Storage,
//private fileOpener: FileOpener,
private sanitiser: DomSanitizer,
// private document: DocumentViewer
private file: File,
private fileOpener: FileOpener,
private router: Router,
// public RochetChatConnectorService: RochetChatConnectorService,
private FileValidatorService: FileValidatorService,
///
private roomRepositoryService: RoomRepositoryService,
private messageRepositoryService: MessageRepositoryService,
private userTypingServiceRepository: UserTypingServiceRepository,
private chatServiceService: ChatServiceService,
private CameraService: CameraService,
private FilePickerService: FilePickerService,
private FilePickerMobileService: FilePickerMobileService
) {
@@ -184,16 +176,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.roomMembers$ = this.roomRepositoryService.getRoomMemberByIdLive(this.roomId) as any
this.roomStatus$ = this.roomRepositoryService.getRoomStatus(this.roomId)
this.roomRepositoryService.getRoomById(this.roomId)
// this.messageRepositoryService.listAllMessagesByRoomId(this.roomId)
this.userTypingServiceRepository.getUserTypingLive().subscribe((e) => {
const arrayNames = e.map(e => e.userName)
this.userTyping$ = e as any
const uniqueArray = [...new Set(arrayNames)];
//(this.myInputRef.nativeElement as HTMLDivElement).innerHTML = '::'+ uniqueArray
})
this.newMessagesStream?.unsubscribe()
this.newMessagesStream = this.messageRepositoryService.subscribeToNewMessages(this.roomId).subscribe((e) => {
@@ -255,23 +237,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
}
ngOnInit() {
try {
// console.log(this.router.url);
this.createDirectoryImage()
// this.chatService.refreshtoken();
// this.ChatSystemService.getUserOfRoom(this.roomId).then((value) => {
// }).catch((error) => {
// console.error(error)
// })
this.getChatMembers();
} catch (error) {
//alert(error)
}
}
ngOnInit() {}
ngAfterViewInit() {
@@ -495,10 +461,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.selectedMsgId = "";
}
deleteMessage(msgId: string) {
// const room = this.ChatSystemService.getDmRoom(this.roomId)
// this.alertService.confirmDeleteMessage(msgId, room);
}
deleteMessage(msgId: string) {}
notImplemented() {
@@ -598,20 +561,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
this.textField = ''
}
/* sendMessage(msg) {
let lastMsg = msg.pop();
console.log(msg)
console.log(lastMsg._id,lastMsg.u.username,lastMsg.msg)
this.ChatSystemService.getDmRoom(this.roomId).send({}).then(() => {
if(lastMsg.u.username == this.members[1].username) {
this.notificationService.ChatSendMessageNotification(this.members[0].username,this.members[1].name,lastMsg.msg,this.roomId)
} else if (msg.u.username == this.members[0].username) {
this.notificationService.ChatSendMessageNotification(this.members[1].username,this.members[1].name,lastMsg.msg,this.roomId)
}
})
} */
async sendAudio(fileName) {
const roomId = this.roomId
let audioFile;
@@ -644,12 +593,15 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
fileName: "audio",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Audio,
mimeType: audioMimeType
mimeType: audioMimeType,
safeFile: this.sanitiser.bypassSecurityTrustResourceUrl(this.audioRecorded)
}]
this.messages1[this.roomId].push(message)
this.chatServiceService.sendMessage(message)
setTimeout(() => {
this.scrollToBottomClicked()
}, 100)
});
this.deleteRecording();
@@ -721,17 +673,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
await modal.present();
}
getChatMembers() {
// this.showLoader = true;
// this.chatService.getMembers(this.roomId).subscribe(res => {
// this.members = res['members'];
// this.dmUsers = res['members'].filter(data => data.username != this.sessionStore.user.UserName)
// this.showLoader = false;
// });
// this.members = this.ChatSystemService.getDmRoom(this.roomId).members
// this.dmUsers = this.ChatSystemService.getDmRoom(this.roomId).membersExcludeMe
}
getChatMembers() {}
showDateDuration(start: any) {
let end;
@@ -801,47 +743,8 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
async takePictureMobile() {
const picture = await this.CameraService.takePicture({
cameraResultType: CameraResultType.DataUrl,
quality: 90
})
this.addFileToChatMobile()
if(picture.isOk()) {
const file = picture.value
const compressedImage = await compressImageBase64(
file.dataUrl,
800, // maxWidth
800, // maxHeight
0.9 // quality
)
if(compressedImage.isOk()) {
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: compressedImage.value.split(',')[1],
fileName: "foto",
source: MessageAttachmentSource.Device,
fileType: MessageAttachmentFileType.Image,
mimeType: 'image/'+picture.value.format
}]
this.messages1[this.roomId].push(message)
this.chatServiceService.sendMessage(message)
}
}
}
@@ -969,59 +872,59 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
}
// async addFileToChatMobile() {
// const roomId = this.roomId
async addFileToChatMobile() {
const roomId = this.roomId
// const file = await Camera.getPhoto({
// quality: 90,
// // allowEditing: true,
// resultType: CameraResultType.Base64,
// source: CameraSource.Photos
// });
const file = await Camera.getPhoto({
quality: 90,
// allowEditing: true,
resultType: CameraResultType.Base64,
source: CameraSource.Photos
});
// //const imageData = await this.fileToBase64Service.convert(file)
// //
//const imageData = await this.fileToBase64Service.convert(file)
//
// var imageBase64 = 'data:image/jpeg;base64,' + file.base64String
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
// });
const compressedImage = await this.compressImageBase64(
imageBase64,
800, // maxWidth
800, // maxHeight
0.9 // quality
).then((picture) => {
console.log('Selected: ', picture)
imageBase64 = picture
});
// //console.log(imageBase64)
//console.log(imageBase64)
// const response = await fetch(imageBase64);
// const blob = await response.blob();
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)
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,
// // }
// // })
// 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();