From 650c772084c2cac10f8f73f452be51de8d569d3c Mon Sep 17 00:00:00 2001 From: Peter Maquiran Date: Sat, 17 Aug 2024 22:05:57 +0100 Subject: [PATCH] improve chat --- .gitignore | 3 + package-lock.json | 198 ++++++++ package.json | 7 +- src/app/app.module.ts | 2 - src/app/controller/event.ts | 2 +- src/app/home/home-routing.module.ts | 60 +-- .../infra/file-picker/file-picker.service.ts | 38 +- .../mobile/file-picker-mobile.service.ts | 15 +- .../dexie/dexie-repository.service.ts | 7 + .../chat-options-features.page.ts | 9 +- src/app/models/chatMethod.ts | 390 --------------- .../chat/domain/chat-service.service.ts | 10 +- ...sage-attachment-localy-use-case.service.ts | 33 ++ ...essage-attachment-by-message-id.service.ts | 41 +- .../message-create-use-case.service.ts | 8 +- .../send-local-messages-use-case.service.ts | 81 +++ .../infra/database/dexie/schema/attachment.ts | 11 +- .../infra/database/dexie/schema/message.ts | 3 +- .../chat/infra/database/dexie/service.ts | 13 +- .../new-publication/new-publication.page.ts | 15 +- src/app/services/chat.service.ts | 436 ---------------- src/app/services/functions/time.service.ts | 1 - src/app/services/notifications.service.ts | 1 - .../new-publication/new-publication.page.ts | 2 - .../store/chat/chat-message.service.spec.ts | 16 - src/app/store/chat/chat-message.service.ts | 46 -- src/app/store/chat/chat-user.service.spec.ts | 16 - src/app/store/chat/chat-user.service.ts | 47 -- src/app/ui/chat/chat.page.ts | 4 - .../component/edit-group/edit-group.page.ts | 28 +- .../group-messages/group-messages.page.ts | 5 - .../component/messages/messages.page.html | 11 +- .../chat/component/messages/messages.page.ts | 66 +-- .../modal/chat-popover/chat-popover.page.ts | 1 - .../chat/modal/edit-group/edit-group.page.ts | 42 +- .../group-contacts/group-contacts.page.ts | 35 +- .../group-messages/group-messages.page.ts | 44 -- .../messages-options/messages-options.page.ts | 5 - .../modal/messages/contacts/contacts.page.ts | 6 +- .../ui/chat/modal/messages/messages.page.html | 4 +- .../ui/chat/modal/messages/messages.page.ts | 466 ++++++------------ src/app/ui/chat/utils/lastMessage.ts | 23 + src/app/utils/ToBase64.ts | 1 + 43 files changed, 712 insertions(+), 1540 deletions(-) delete mode 100644 src/app/models/chatMethod.ts create mode 100644 src/app/module/chat/domain/use-case/get-message-attachment-localy-use-case.service.ts create mode 100644 src/app/module/chat/domain/use-case/send-local-messages-use-case.service.ts delete mode 100644 src/app/services/chat.service.ts delete mode 100644 src/app/store/chat/chat-message.service.spec.ts delete mode 100644 src/app/store/chat/chat-message.service.ts delete mode 100644 src/app/store/chat/chat-user.service.spec.ts delete mode 100644 src/app/store/chat/chat-user.service.ts create mode 100644 src/app/ui/chat/utils/lastMessage.ts diff --git a/.gitignore b/.gitignore index ddf3d9873..6aeef717d 100644 --- a/.gitignore +++ b/.gitignore @@ -101,3 +101,6 @@ plugin copy pm2.yaml doc/TypeDoc/** doc/TypeDoc + +# Sentry Config File +.sentryclirc diff --git a/package-lock.json b/package-lock.json index dc8850157..b2f72e1ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -108,6 +108,7 @@ "@pdftron/pdfjs-express": "^8.0.1", "@sentry/angular": "7.73.0", "@sentry/capacitor": "^0.14.0", + "@sentry/cli": "^2.33.1", "@teamhive/capacitor-video-recorder": "^5.0.0", "@tinymce/tinymce-angular": "^4.2.4", "@types/jest-environment-puppeteer": "^5.0.3", @@ -8230,6 +8231,142 @@ } } }, + "node_modules/@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "cpu": [ + "x86", + "ia32" + ], + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "cpu": [ + "x86", + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@sentry/core": { "version": "7.73.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.73.0.tgz", @@ -50313,6 +50450,67 @@ "@sentry/utils": "7.73.0" } }, + "@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "requires": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + } + }, + "@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "optional": true + }, + "@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "optional": true + }, + "@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "optional": true + }, + "@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "optional": true + }, + "@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "optional": true + }, + "@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "optional": true + }, + "@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "optional": true + }, "@sentry/core": { "version": "7.73.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.73.0.tgz", diff --git a/package.json b/package.json index 024216170..ace32ee00 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,9 @@ "docker:publish": "docker run -p gabinetedigital:0.0.0.1", "build:oapr": "ionic cap build android --configuration oapr", "build:dev": "ionic cap build android --configuration dev", - "doc:generate": "rimraf doc/TypeDoc && typedoc " + "doc:generate": "rimraf doc/TypeDoc && typedoc ", + "build-and-upload-sourcemaps": "ng build --prod && sentry-cli releases files $(jq -r .version package.json) upload-sourcemaps ./www --url-prefix '~' --rewrite", + "sentry:sourcemaps": "sentry-cli sourcemaps inject --org equilibrium-sa --project oapr-gabinetedigital-fo ./www && sentry-cli sourcemaps upload --org equilibrium-sa --project oapr-gabinetedigital-fo ./www" }, "private": true, "dependencies": { @@ -125,6 +127,7 @@ "@pdftron/pdfjs-express": "^8.0.1", "@sentry/angular": "7.73.0", "@sentry/capacitor": "^0.14.0", + "@sentry/cli": "^2.33.1", "@teamhive/capacitor-video-recorder": "^5.0.0", "@tinymce/tinymce-angular": "^4.2.4", "@types/jest-environment-puppeteer": "^5.0.3", @@ -327,4 +330,4 @@ "url": "git+https://Kayaya@bitbucket.org/equilibriumito/gabinete-digital.git" }, "license": "ISC" -} +} \ No newline at end of file diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 021f4fbaa..0064d16d6 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -22,7 +22,6 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { CalendarModule, DateAdapter } from 'angular-calendar'; import { adapterFactory } from 'angular-calendar/date-adapters/date-fns'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ChatService } from './services/chat.service'; import {MatDatepickerModule} from '@angular/material/datepicker'; import {MAT_DATE_LOCALE} from '@angular/material/core'; import { Network } from '@ionic-native/network/ngx'; @@ -238,7 +237,6 @@ export function counterReducer(state, action) { FilePath, /* FCM, FirebaseX, */ - ChatService, ScreenOrientation, Network, SQLite, diff --git a/src/app/controller/event.ts b/src/app/controller/event.ts index fa353ef70..b08488d20 100644 --- a/src/app/controller/event.ts +++ b/src/app/controller/event.ts @@ -1,4 +1,4 @@ -import { chatUser } from '../models/chatMethod' + //import { ChatController } from './chat' export class EventController { static create() { diff --git a/src/app/home/home-routing.module.ts b/src/app/home/home-routing.module.ts index 39b260343..3e49758f9 100644 --- a/src/app/home/home-routing.module.ts +++ b/src/app/home/home-routing.module.ts @@ -288,37 +288,37 @@ const routes: Routes = [ ], }, - // { - // path: 'publications', - // children: [ - // { - // path:'', - // loadChildren: ()=> PublicationsPageModule - // }, - // { - // path:':folderId', - // loadChildren: ()=> import('../pages/publications/view-publications/view-publications.module').then(m => m.ViewPublicationsPageModule) - // }, - // { - // path:'view-publications', - // children: [ - // { - // path:':folderId/:publicationId', - // loadChildren: ()=> import('../pages/publications/view-publications/publication-detail/publication-detail.module').then(m => m.PublicationDetailPageModule) - // }, - // ] - // }, - // { - // path:'new-publication', - // loadChildren: ()=> import('../shared/publication/new-publication/new-publication.module').then(m => m.NewPublicationPageModule) - // }, - // { - // path: 'request-options', - // loadChildren: () => import('../shared/popover/request-options/request-options.module').then( m => m.RequestOptionsPageModule) - // }, - // ], + { + path: 'publications', + children: [ + { + path:'', + loadChildren: ()=> PublicationsPageModule + }, + { + path:':folderId', + loadChildren: ()=> import('../pages/publications/view-publications/view-publications.module').then(m => m.ViewPublicationsPageModule) + }, + { + path:'view-publications', + children: [ + { + path:':folderId/:publicationId', + loadChildren: ()=> import('../pages/publications/view-publications/publication-detail/publication-detail.module').then(m => m.PublicationDetailPageModule) + }, + ] + }, + { + path:'new-publication', + loadChildren: ()=> import('../shared/publication/new-publication/new-publication.module').then(m => m.NewPublicationPageModule) + }, + { + path: 'request-options', + loadChildren: () => import('../shared/popover/request-options/request-options.module').then( m => m.RequestOptionsPageModule) + }, + ], - // }, + }, { path: 'chat', children: [ diff --git a/src/app/infra/file-picker/file-picker.service.ts b/src/app/infra/file-picker/file-picker.service.ts index 26f344b8c..c4e5db745 100644 --- a/src/app/infra/file-picker/file-picker.service.ts +++ b/src/app/infra/file-picker/file-picker.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; -import { Camera, CameraResultType, CameraSource } from '@capacitor/camera'; -import { err, ok } from 'neverthrow'; +import { Camera, CameraPhoto, CameraResultType, CameraSource } from '@capacitor/camera'; +import { err, ok, Result } from 'neverthrow'; /** * Parameters for picking a picture. @@ -13,6 +13,15 @@ type PickPictureParams = { cameraResultType?: CameraResultType; }; +/** + * Error types for the FilePickerService. + */ +export interface FilePickerError { + type: 'PERMISSION_DENIED' | 'CANCELLED' | 'UNKNOWN'; + message: string; + originalError?: any; +} + /** * Service for handling file picking functionality. * This service provides methods to pick a picture from the device's photo library. @@ -22,9 +31,6 @@ type PickPictureParams = { }) export class FilePickerService { - /** - * Creates an instance of FilePickerService. - */ constructor() { } /** @@ -34,7 +40,7 @@ export class FilePickerService { * @param {CameraResultType} [params.cameraResultType=CameraResultType.DataUrl] - The result type of the photo. Defaults to `CameraResultType.DataUrl`. * @returns {Promise | err>} 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) { + async getPicture({quality = 90, cameraResultType = CameraResultType.DataUrl }: PickPictureParams): Promise> { try { const file = await Camera.getPhoto({ quality: quality, @@ -44,7 +50,25 @@ export class FilePickerService { return ok(file); } catch (e) { - return err(e); + if (e.message.includes('denied')) { + return err({ + type: 'PERMISSION_DENIED', + message: 'Permission to access photos was denied.', + originalError: e + }); + } else if (e.message.includes('User cancelled photos app')) { + return err({ + type: 'CANCELLED', + message: 'User cancelled the photo selection.', + originalError: e + }); + } else { + return err({ + type: 'UNKNOWN', + message: 'An unknown error occurred while picking the picture.', + originalError: e + }); + } } } } diff --git a/src/app/infra/file-picker/mobile/file-picker-mobile.service.ts b/src/app/infra/file-picker/mobile/file-picker-mobile.service.ts index b7228276e..2d4fad859 100644 --- a/src/app/infra/file-picker/mobile/file-picker-mobile.service.ts +++ b/src/app/infra/file-picker/mobile/file-picker-mobile.service.ts @@ -9,14 +9,21 @@ export class FilePickerMobileService { constructor() { } + /** + * @example + * ```typescript + * const types = ['application/pdf', 'application/doc', 'application/docx','application/xls', 'application/xlsx', 'application/ppt','application/pptx', 'application/txt']; + * const multiple = false; // Invalid due to commas + * const readData = true; // Invalid due to commas + * ``` + */ async getFile({types, multiple, readData}): Promise> { 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, + types: types, + multiple: multiple, + readData: readData, }); return ok(result) diff --git a/src/app/infra/repository/dexie/dexie-repository.service.ts b/src/app/infra/repository/dexie/dexie-repository.service.ts index 68ae8687b..26e574060 100644 --- a/src/app/infra/repository/dexie/dexie-repository.service.ts +++ b/src/app/infra/repository/dexie/dexie-repository.service.ts @@ -1,6 +1,7 @@ import { Result, ok, err } from 'neverthrow'; import { EntityTable } from 'Dexie'; import { ZodError, ZodObject, ZodSchema } from 'zod'; +import { Logger } from 'src/app/services/logger/main/service'; // Define a type for the Result of repository operations type RepositoryResult = Result>; @@ -28,6 +29,9 @@ export class DexieRepository { return err(new Error('Failed to insert document: ' + error.message)); } } else { + Logger.error(`dexie.js failed to insert into ${this.table.name}, invalid data`, { + data: document + }); return err((dataValidation as unknown as ZodError)) } } @@ -45,6 +49,9 @@ export class DexieRepository { const ids = await this.table.bulkAdd(documents as any); return ok(ids); } catch (error) { + Logger.error(`dexie.js failed to insert many into ${this.table.name}, invalid data`, { + data: document + }); return err(new Error('Failed to insert multiple documents: ' + error.message)); } } diff --git a/src/app/modals/chat-options-features/chat-options-features.page.ts b/src/app/modals/chat-options-features/chat-options-features.page.ts index 70794ecab..6529f9c81 100644 --- a/src/app/modals/chat-options-features/chat-options-features.page.ts +++ b/src/app/modals/chat-options-features/chat-options-features.page.ts @@ -5,7 +5,6 @@ import { SearchList } from 'src/app/models/search-document'; import { NewEventPage } from 'src/app/pages/agenda/new-event/new-event.page'; import { SearchPage } from 'src/app/pages/search/search.page'; import { AlertService } from 'src/app/services/alert.service'; -import { ChatService } from 'src/app/services/chat.service'; import { FileLoaderService } from 'src/app/services/file/file-loader.service'; import { FileToBase64Service } from 'src/app/services/file/file-to-base64.service'; import { environment } from 'src/environments/environment'; @@ -33,7 +32,6 @@ export class ChatOptionsFeaturesPage implements OnInit { private navParams: NavParams, private fileLoaderService: FileLoaderService, private fileToBase64Service: FileToBase64Service, - private chatService: ChatService, public ThemeService: ThemeService ) { @@ -121,9 +119,7 @@ export class ChatOptionsFeaturesPage implements OnInit { } } - this.chatService.sendMessage(body).subscribe(res=> { - // - }); + // }; } @@ -145,10 +141,7 @@ export class ChatOptionsFeaturesPage implements OnInit { } } - this.chatService.sendMessage(body).subscribe(res=> { - - }); } /* getGroupContacts(room:any){ diff --git a/src/app/models/chatMethod.ts b/src/app/models/chatMethod.ts deleted file mode 100644 index e1ac3a2ba..000000000 --- a/src/app/models/chatMethod.ts +++ /dev/null @@ -1,390 +0,0 @@ -interface Ts { - $date: any; -} - -interface U { - _id: string; - username: string; - name: string; -} - -interface UpdatedAt { - $date: any; -} - -interface Attachment { - ts: Date; - title_link_download: boolean; -} - -export interface File { - type: string; - guid: string; - image_url: string; - subject: string; - start_date?: Date; - end_date?: Date; - venue: string; - id: string; -} - -interface EditedAt { - $date: number; -} - -interface EditedBy { - _id: string; - username: string; -} - - - -interface Ts2 { - $date: number; -} - -interface U2 { - _id: string; - username: string; - name: string; -} - -interface UpdatedAt2 { - $date: number; -} - -interface FirstUnread { - _id: string; - rid: string; - msg: string; - ts: Ts2; - u: U2; - _updatedAt: string; - mentions: any[]; - channels: any[]; -} - -export interface Message { - customFields:any; - _id: string; - id: null | string; - rid: string; - msg: string; - ts: Ts; - sendAttempt?: number - u: U; - from: 'Offline'|'History'|'stream'| 'send' - t: string; - origin: 'history' | 'stream' | 'local' - _updatedAt: ''; - mentions: any[]; - channels: any[]; - attachments: Attachment[]; - file: File; - editedAt: EditedAt; - editedBy: EditedBy; - urls: any[]; - temporaryData: object - localReference?: string, - viewed: string[], - received: string[], - delate: boolean, - delateRequest: boolean - attachmentsModelData: { - fileBase64: string - } - hasFile: boolean - UploadAttachmentsTemp: number -} - - - - -export interface Lm { - $date: any; -} - - - - -export interface LastMessage { - _id: string; - rid: string; - msg: string; - ts: Ts; - u: U; - _updatedAt: UpdatedAt2; - mentions: any[]; - channels: any[]; - file: File; - attachments: Attachment[]; -} - -export interface CustomFields { -} - -export interface Update { - _id: string; - t: string; - usernames: string[]; - usersCount: number; - uids: string[]; - default: boolean; - ro: boolean; - sysMes: boolean; - _updatedAt: UpdatedAt; - lm: Lm; - lastMessage: LastMessage; - name: string; - fname: string; - u: U2; - customFields: CustomFields; -} - -export interface DeletedAt { - $date: any; -} - -export interface Remove { - _id: string; - _deletedAt: DeletedAt; -} - -export interface Result { - update: Update[]; - remove: Remove[]; -} - -export interface Rooms { - msg: string; - id: string; - result: Result; -} - - - -export interface ChatMessage { - msg: string; - id: string; - result: Message -} - - - - - -export interface chatHistory { - msg: string; - id: string; - result: { - messages: Message[]; - firstUnread: FirstUnread; - unreadNotLoaded: number; - }; -} - - - - -interface Ts { - $date: any; -} - -interface U { - _id: string; - username: string; - name: string; -} - -interface UpdatedAt { - $date: any; -} - -interface Attachment { - ts: Date; - title_link_download: boolean; -} - -export interface File { - type: string; - guid: string; - image_url: string; - subject: string; - start_date?: Date; - end_date?: Date; - venue: string; - id: string; -} - -interface EditedAt { - $date: number; -} - -interface EditedBy { - _id: string; - username: string; -} - - - -interface Ts2 { - $date: number; -} - -interface U2 { - _id: string; - username: string; - name: string; -} - -interface UpdatedAt2 { - $date: number; -} - -interface FirstUnread { - _id: string; - rid: string; - msg: string; - ts: Ts2; - u: U2; - _updatedAt: string; - mentions: any[]; - channels: any[]; -} - -export interface Message { - customFields:any; - _id: string; - rid: string; - msg: string; - ts: Ts; - u: U; - t: string; - _updatedAt: ''; - mentions: any[]; - channels: any[]; - attachments: Attachment[]; - file: File; - editedAt: EditedAt; - editedBy: EditedBy; - urls: any[]; -} - - - - -export interface Lm { - $date: any; -} - - - - -export interface LastMessage { - _id: string; - rid: string; - msg: string; - ts: Ts; - u: U; - _updatedAt: UpdatedAt2; - mentions: any[]; - channels: any[]; - file: File; - attachments: Attachment[]; -} - -export interface CustomFields { -} - -export interface Update { - _id: string; - t: string; - usernames: string[]; - usersCount: number; - uids: string[]; - default: boolean; - ro: boolean; - sysMes: boolean; - _updatedAt: UpdatedAt; - lm: Lm; - lastMessage: LastMessage; - name: string; - fname: string; - u: U2; - customFields: CustomFields; -} - -export interface DeletedAt { - $date: any; -} - -export interface Remove { - _id: string; - _deletedAt: DeletedAt; -} - -export interface Result { - update: Update[]; - remove: Remove[]; -} - -export interface Rooms { - msg: string; - id: string; - result: Result; -} - - - -export interface ChatMessage { - msg: string; - id: string; - result: Message -} - - - - - -export interface chatHistory { - msg: string; - id: string; - result: { - messages: Message[]; - firstUnread: FirstUnread; - unreadNotLoaded: number; - }; -} - -export interface chatUser { - _id: string; - createdAt: Date; - emails: { - address: string; - verified: boolean; - } - type: string; - status: 'online' | 'offline' | 'away' | 'busy' ; - active: boolean; - _updatedAt: Date; - roles: string[]; - name: string; - lastLogin: Date; - statusConnection: string; - utcOffset: number; - username: string; - __rooms: string[]; - requirePasswordChange?: boolean; - settings: { - preferences: { - language: string; - }; - }; - nickname: string; - statusText: string; - banners: any; - statusDefault: string; - language: string; - avatarOrigin: string; - avatarETag?: any; -} \ No newline at end of file diff --git a/src/app/module/chat/domain/chat-service.service.ts b/src/app/module/chat/domain/chat-service.service.ts index fd15532fc..a7328fb8a 100644 --- a/src/app/module/chat/domain/chat-service.service.ts +++ b/src/app/module/chat/domain/chat-service.service.ts @@ -16,6 +16,7 @@ import { ListenMessageDeleteByRoomIdService } from './use-case/listene-message-d import { ListenMessageUpdateByRoomIdUseCase } from './use-case/listen-message-update-by-roomId.service'; import { SyncAllRoomMessagesService } from './use-case/sync-all-room-messages.service'; import { ListenSendMessageUseCase } from './use-case/listen-send-message.service' +import { GetMessageAttachmentLocallyUseCaseService } from 'src/app/module/chat/domain/use-case/get-message-attachment-localy-use-case.service'; import { filter } from 'rxjs/operators'; import { v4 as uuidv4 } from 'uuid' import { MessageEntity } from './entity/message'; @@ -46,7 +47,8 @@ export class ChatServiceService { private ListenSendMessageUseCase: ListenSendMessageUseCase, private MessageAttachmentByMessageIdService: MessageAttachmentByMessageIdUseCase, private SyncAllRoomMessagesService: SyncAllRoomMessagesService, - private DownloadMessageAttachmentUserCaseService: DownloadMessageAttachmentUserCaseService + private DownloadMessageAttachmentUserCaseService: DownloadMessageAttachmentUserCaseService, + private GetMessageAttachmentLocallyUseCaseService: GetMessageAttachmentLocallyUseCaseService ) { this.messageLiveSignalRDataSourceService.getMessageDelete() .pipe() @@ -127,7 +129,7 @@ export class ChatServiceService { return this.SyncAllRoomMessagesService.execute() } - getMessageAttachmentByMessageId(input: MessageAttachmentByMessageIdInput) { + getMessageAttachmentByMessageId(input: MessageEntity) { return this.MessageAttachmentByMessageIdService.execute(input) } @@ -135,6 +137,10 @@ export class ChatServiceService { return this.DownloadMessageAttachmentUserCaseService.execute(input) } + getMessageAttachmentLocallyByMessageId(input: MessageAttachmentByMessageIdInput) { + return this.GetMessageAttachmentLocallyUseCaseService.execute(input) + } + listenToIncomingMessage(roomId:string) { return this.ListenMessageByRoomIdNewUseCase.execute({roomId}) diff --git a/src/app/module/chat/domain/use-case/get-message-attachment-localy-use-case.service.ts b/src/app/module/chat/domain/use-case/get-message-attachment-localy-use-case.service.ts new file mode 100644 index 000000000..bd2381a59 --- /dev/null +++ b/src/app/module/chat/domain/use-case/get-message-attachment-localy-use-case.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import { MessageAttachmentByMessageIdInput } from './message-attachment-by-message-id.service'; +import { AttachmentRemoteDataSourceService } from 'src/app/module/chat/data/data-source/attachment/attachment-remote-data-source.service' +import { AttachmentLocalDataSource } from 'src/app/module/chat/data/data-source/attachment/attachment-local-data-source.service' +import { err, Result } from 'neverthrow'; + +@Injectable({ + providedIn: 'root' +}) +export class GetMessageAttachmentLocallyUseCaseService { + + constructor( + private AttachmentRemoteDataSourceService: AttachmentRemoteDataSourceService, + private AttachmentLocalDataSource: AttachmentLocalDataSource + ) { } + + + async execute(input: MessageAttachmentByMessageIdInput): Promise> { + + const getLocalAttachment = await this.AttachmentLocalDataSource.findOne({ + $messageId: input.$messageId + }) + + if(getLocalAttachment.isOk()) { + if(getLocalAttachment.value) { + return getLocalAttachment.map(e => e.file) + } + } else { + return err(getLocalAttachment.error) + } + } + +} diff --git a/src/app/module/chat/domain/use-case/message-attachment-by-message-id.service.ts b/src/app/module/chat/domain/use-case/message-attachment-by-message-id.service.ts index 66808fb8b..97e02a504 100644 --- a/src/app/module/chat/domain/use-case/message-attachment-by-message-id.service.ts +++ b/src/app/module/chat/domain/use-case/message-attachment-by-message-id.service.ts @@ -5,6 +5,7 @@ import { AttachmentLocalDataSource } from 'src/app/module/chat/data/data-source/ import { convertBlobToDataURL } from 'src/app/utils/ToBase64'; import { Result } from 'neverthrow'; import { Logger } from 'src/app/services/logger/main/service'; +import { MessageEntity } from '../entity/message'; const MessageAttachmentByMessageIdSchema = z.object({ $messageId: z.number(), @@ -23,10 +24,10 @@ export class MessageAttachmentByMessageIdUseCase { private AttachmentLocalDataSource: AttachmentLocalDataSource ) { } - async execute(input: MessageAttachmentByMessageIdInput): Promise> { + async execute(input: MessageEntity): Promise> { const getLocalAttachment = await this.AttachmentLocalDataSource.findOne({ - $messageId: input.$messageId + $messageId: input.$id }) if(getLocalAttachment.isOk() && getLocalAttachment.value) { @@ -34,18 +35,40 @@ export class MessageAttachmentByMessageIdUseCase { return getLocalAttachment.map(e => e.file) } } else { - const result = await this.AttachmentRemoteDataSourceService.getAttachment(input.id) + const result = await this.AttachmentRemoteDataSourceService.getAttachment(input.attachments[0].id) + + if(result.isErr()) { + Logger.error('failed to download message attachment', { + error: result.error, + data: 'document id '+ input.attachments[0].id, + messageId: input.id, + $messageId: input.$id + }) + } + return result.asyncMap(async (e) => { const dataUrl = await convertBlobToDataURL(e) - Logger.info('downloaded file', { - data: dataUrl.slice(0, 100)+'...' - }) + // Logger.info('downloaded file .', { + // data: dataUrl.slice(0, 100)+'...' + // }) this.AttachmentLocalDataSource.insert({ - $messageId: input.$messageId, - id: input.id, - file: dataUrl + $messageId: input.$id, + file: dataUrl, + fileType: input.attachments[0].fileType, + source: input.attachments[0].source, + fileName: input.attachments[0].fileName, + applicationId: input.attachments[0].applicationId, + docId: input.attachments[0].docId, + mimeType: input.attachments[0].mimeType, + }).then((e) => { + if(e.isErr()) { + Logger.error('failed to create attachment locally on send message', { + error: e.error, + data: dataUrl.slice(0, 100)+'...' + }) + } }) return dataUrl diff --git a/src/app/module/chat/domain/use-case/message-create-use-case.service.ts b/src/app/module/chat/domain/use-case/message-create-use-case.service.ts index d3194d563..80d1f1406 100644 --- a/src/app/module/chat/domain/use-case/message-create-use-case.service.ts +++ b/src/app/module/chat/domain/use-case/message-create-use-case.service.ts @@ -49,7 +49,13 @@ export class MessageCreateUseCaseService { this.AttachmentRepositoryService.create({ $messageId: createMessageLocally.value.$id, - file: createDataURL(attachment.file, attachment.mimeType) + file: createDataURL(attachment.file, attachment.mimeType), + fileType: attachment.fileType, + source: attachment.source, + fileName: attachment.fileName, + applicationId: attachment.applicationId, + docId: attachment.docId, + mimeType: attachment.mimeType, }).then((e) => { if(e.isErr()) { Logger.error('failed to create attachment locally on send message', { diff --git a/src/app/module/chat/domain/use-case/send-local-messages-use-case.service.ts b/src/app/module/chat/domain/use-case/send-local-messages-use-case.service.ts new file mode 100644 index 000000000..4e30fb9cc --- /dev/null +++ b/src/app/module/chat/domain/use-case/send-local-messages-use-case.service.ts @@ -0,0 +1,81 @@ +import { Injectable } from '@angular/core'; +import { MessageLocalDataSourceService } from '../../data/data-source/message/message-local-data-source.service'; +import { MessageOutPutDataDTO } from '../../data/dto/message/messageOutputDTO'; +import { MessageTable } from '../../infra/database/dexie/schema/message'; +import { SignalRService } from '../../infra/socket/signal-r.service'; +import { InstanceId } from '../chat-service.service'; +import { MessageMapper } from '../mapper/messageMapper'; +import { v4 as uuidv4 } from 'uuid' +import { AttachmentRepositoryService } from "src/app/module/chat/data/repository/attachment-repository.service"; +import { AttachmentLocalDataSource } from '../../data/data-source/attachment/attachment-local-data-source.service'; + +@Injectable({ + providedIn: 'root' +}) +export class SendLocalMessagesUseCaseService { + + constructor( + private messageLiveSignalRDataSourceService: SignalRService, + private messageLocalDataSourceService: MessageLocalDataSourceService, + private AttachmentRepositoryService: AttachmentLocalDataSource, + ) { } + + + async execute() { + const messages = await this.messageLocalDataSourceService.getOfflineMessages() + + if(messages.length >= 1) { + + for(const message of messages) { + + const attachments = await this.AttachmentRepositoryService.find({$messageId: message.$id}) + + if(attachments.isOk()) { + + message.attachments = attachments.value.map(e => ({ + fileType: e.fileType, + source: e.source, + fileName: e.fileName, + applicationId: e.applicationId, + docId: e.docId, + id: e.id, + mimeType: e.mimeType, + description: e.description, + file: e.file.split(',')[0] + })) + console.log('to upload', messages) + const requestId = InstanceId +'@'+ uuidv4(); + const DTO = MessageMapper.fromDomain(message, requestId) + + await this.messageLocalDataSourceService.update(message.$id, { sending: true }) + const sendMessageResult = await this.messageLiveSignalRDataSourceService.sendMessage(DTO) + + if(sendMessageResult.isOk()) { + + if(sendMessageResult.value.sender == undefined || sendMessageResult.value.sender == null) { + + delete sendMessageResult.value.sender + } + + let clone: MessageTable = { + ...sendMessageResult.value, + id: sendMessageResult.value.id, + $id : message.$id + } + + console.log('send message local '+ messages.length) + + this.messageLocalDataSourceService.update(message.$id, {...clone, sending: false, roomId: message.roomId}) + } else { + + console.log('erro send message') + this.messageLocalDataSourceService.update(message.$id, {sending: false}) + } + } + + + } + + } + } +} diff --git a/src/app/module/chat/infra/database/dexie/schema/attachment.ts b/src/app/module/chat/infra/database/dexie/schema/attachment.ts index c7a830436..77c83afdc 100644 --- a/src/app/module/chat/infra/database/dexie/schema/attachment.ts +++ b/src/app/module/chat/infra/database/dexie/schema/attachment.ts @@ -1,13 +1,22 @@ import { z } from "zod"; import { EntityTable } from 'Dexie'; import { zodDataUrlSchema } from "src/app/utils/zod"; +import { MessageAttachmentFileType, MessageAttachmentSource } from "src/app/module/chat/data/dto/message/messageOutputDTO"; export const AttachmentTableSchema = z.object({ - id: z.string().optional(), // attachment id $id: z.number().optional(), // local id $messageId: z.number(), attachmentId: z.string().optional(), file: zodDataUrlSchema, + // + fileType: z.nativeEnum(MessageAttachmentFileType), + source: z.nativeEnum(MessageAttachmentSource), + fileName: z.string().optional(), + applicationId: z.number().optional(), + docId: z.string().optional(), + mimeType: z.string().optional(), + id: z.string().optional(), + description: z.string().optional(), }) export type AttachmentTable = z.infer diff --git a/src/app/module/chat/infra/database/dexie/schema/message.ts b/src/app/module/chat/infra/database/dexie/schema/message.ts index 53280ee0b..ccc921346 100644 --- a/src/app/module/chat/infra/database/dexie/schema/message.ts +++ b/src/app/module/chat/infra/database/dexie/schema/message.ts @@ -1,6 +1,6 @@ -import { nativeEnum, z } from "zod"; import { EntityTable } from 'Dexie'; import { MessageAttachmentFileType, MessageAttachmentSource } from "src/app/module/chat/data/dto/message/messageOutputDTO"; +import { z } from 'zod'; export const MessageTableSchema = z.object({ $id: z.number().optional(), @@ -33,6 +33,7 @@ export const MessageTableSchema = z.object({ applicationId: z.number().optional(), docId: z.string().optional(), id: z.string().optional(), + description: z.string().optional(), mimeType: z.string().optional() })).optional() }) diff --git a/src/app/module/chat/infra/database/dexie/service.ts b/src/app/module/chat/infra/database/dexie/service.ts index 1063c8c38..78860063d 100644 --- a/src/app/module/chat/infra/database/dexie/service.ts +++ b/src/app/module/chat/infra/database/dexie/service.ts @@ -5,11 +5,16 @@ import { DexieMembersTableSchema, MemberTableColumn } from './schema/members'; import { DexieRoomsTable, RoomTableColumn } from './schema/room'; import { DexieTypingsTable, TypingTableColumn } from './schema/typing'; import { MessageEntity } from '../../../domain/entity/message'; -import { AttachmentTable, AttachmentTableColumn, DexieAttachmentsTableSchema } from './schema/attachment'; -// import DexieMemory from 'dexie-in-memory'; +import { AttachmentTableColumn, DexieAttachmentsTableSchema } from './schema/attachment'; +// import FDBFactory from 'fake-indexeddb/lib/FDBFactory'; +// import FDBKeyRange from 'fake-indexeddb/lib/FDBKeyRange'; + // Database declaration (move this to its own module also) -export const chatDatabase = new Dexie('chat-database-infra') as Dexie & { +export const chatDatabase = new Dexie('chat-database-infra',{ +// indexedDB: new FDBFactory, +// IDBKeyRange: FDBKeyRange, // Mocking IDBKeyRange +}) as Dexie & { message: DexieMessageTable, members: DexieMembersTableSchema, room: DexieRoomsTable, @@ -26,4 +31,4 @@ chatDatabase.version(1).stores({ }); chatDatabase.message.mapToClass(MessageEntity) -// Apply in-memory storage +// Apply in-memory storage \ No newline at end of file diff --git a/src/app/pages/publications/new-publication/new-publication.page.ts b/src/app/pages/publications/new-publication/new-publication.page.ts index 5f276eb87..3761c43fb 100644 --- a/src/app/pages/publications/new-publication/new-publication.page.ts +++ b/src/app/pages/publications/new-publication/new-publication.page.ts @@ -1,10 +1,8 @@ import { Component, OnInit } from '@angular/core'; -import { ModalController, NavParams, Platform, LoadingController } from '@ionic/angular'; +import { ModalController, NavParams, Platform } from '@ionic/angular'; /* import {Plugins, CameraResultType, CameraSource} from '@capacitor/core'; */ import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; -import { PublicationsService } from 'src/app/services/publications.service'; -import { Publication } from 'src/app/models/publication'; import { Image } from 'src/app/models/image'; import { PhotoService } from 'src/app/services/photo.service'; //Capacitor @@ -22,21 +20,16 @@ import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'; import { PublicationFolderService } from 'src/app/store/publication-folder.service'; import { RouteService } from 'src/app/services/route.service'; import { FileService } from 'src/app/services/functions/file.service'; -import { readAndCompressImage } from 'browser-image-resizer'; import { FilePicker } from '@capawesome/capacitor-file-picker'; -import { CapacitorVideoPlayer } from 'capacitor-video-player'; import { CaptureError, CaptureImageOptions, MediaCapture, MediaFile } from '@awesome-cordova-plugins/media-capture/ngx'; -import { Capacitor } from '@capacitor/core'; -import { File as IonicFile } from '@ionic-native/file/ngx'; + import { Media } from '@ionic-native/media/ngx'; import { checkFileTypeService } from 'src/app/services/checkFileType.service'; -import { FileValidatorService } from "src/app/services/file/file-validator.service" import { App } from '@capacitor/app'; import { NavigationExtras, Router } from '@angular/router'; import { VideoconvertService } from 'src/app/services/videoconvert.service' import { PublicationAttachmentEntity } from 'src/app/shared/publication/upload/upload-streaming.service'; import { PublicationFromMvService } from "src/app/shared/publication/upload/publication-from-mv.service" -import { File } from '../../../models/chatMethod'; import { CropImagePage } from 'src/app/modals/crop-image/crop-image.page'; @@ -127,19 +120,15 @@ export class NewPublicationPage implements OnInit { private modalController: ModalController, public photoService: PhotoService, private navParams: NavParams, - private publications: PublicationsService, private toastService: ToastService, public ThemeService: ThemeService, private platform: Platform, - private loadingCtrl: LoadingController, public imageCompress: NgxImageCompressService, private httpErrorHandle: HttpErrorHandle, public PublicationFolderService: PublicationFolderService, - private RouteService: RouteService, public FileService: FileService, private mediaCapture: MediaCapture, public checkFileType: checkFileTypeService, - private FileValidatorService: FileValidatorService, private router: Router, private videoconvertService: VideoconvertService, public PublicationFromMvService: PublicationFromMvService, diff --git a/src/app/services/chat.service.ts b/src/app/services/chat.service.ts deleted file mode 100644 index 3cc3017db..000000000 --- a/src/app/services/chat.service.ts +++ /dev/null @@ -1,436 +0,0 @@ -import { HttpHeaders, HttpParams } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { HttpService } from './http.service'; -import { StorageService } from './storage.service'; -import { HttpClient } from '@angular/common/http'; -import { environment } from 'src/environments/environment'; -import { Storage } from '@ionic/storage'; -import { PermissionService } from './permission.service'; -import { SessionStore } from '../store/session.service'; -import { ChangeProfileService } from 'src/app/services/change-profile.service'; -import { NetworkServiceService , ConnectionStatus} from 'src/app/services/network-service.service'; -// import { RochetChatConnectorService } from 'src/app/services/chat/rochet-chat-connector.service'; - -@Injectable({ - providedIn: 'root' -}) -export class ChatService { - headers: HttpHeaders; - options: any; - options1: any; - X_User_Id: any; - X_Auth_Token: any; - loggedUserChat: any; - bindOnMessage: any; - - constructor( - private http: HttpClient, - private httpService: HttpService, - private storage: Storage, - private storageService: StorageService, - public p: PermissionService, - private changeProfileService: ChangeProfileService, - private NetworkServiceService: NetworkServiceService, - // private RochetChatConnectorService: RochetChatConnectorService - ) { - - this.changeProfileService.registerCallback(() => { - this.setheader(); - }) - - } - - getDocumentDetails(url: string) { - let headersc = new HttpHeaders(); - headersc = headersc.set('X-User-Id', SessionStore.user.ChatData.data.userId); - headersc = headersc.set('X-Auth-Token', SessionStore.user.ChatData.data.authToken); - headersc = headersc.set('Sec-Fetch-Dest', 'attachment'); - headersc = headersc.set('Sec-Fetch-Mode', 'navigate'); - headersc = headersc.set('Cookie', 'rc_uid=fsMwcNdufWvdnChj7'); - headersc = headersc.set('Cookie', 'rc_token=MLbhikLQI4xo9_vL43HqheKPPbxjag7hKfwxe9AjcvY'); - // headersc = headersc.set("Host", "www.tabularium.pt"); - // headersc = headersc.set("Origin", "http://localhost:8100"); - headersc = headersc.set('Referer', 'http://localhost:8100/'); - let optionsc = { - headers: headersc, - withCredentials: true - }; - // let fullUrl = "https://www.tabularium.pt/" + url; - return this.http.get(url, optionsc).subscribe(() => { - // this.fileService.viewDocumentByUrl(url) - }); - } - - getAllChannels() { - return this.http.get(environment.apiChatUrl + 'channels.list', this.options); - } - - getAllUserChannels() { - return this.http.get(environment.apiChatUrl + 'channels.list.joined', this.options); - } - - getAllRooms() { - return this.http.get(environment.apiChatUrl + 'rooms.get', this.options); - } - - getRoomInfo(roomId: any) { - let params = new HttpParams(); - params = params.set("roomId", roomId); - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'rooms.info', opts); - } - - - GetSubscriptionRoomUnreadM(roomId) { - let params = new HttpParams(); - params = params.set("roomId", roomId); - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'subscriptions.getOne', opts); - } - - getChannelInfo(roomId: any) { - let params = new HttpParams(); - params = params.set("roomId", roomId); - params = params.set("unread", "true"); - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'rooms.info', opts); - } - - customsRooms(params: any) { - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'rooms.get', opts); - } - getAllPrivateGroups() { - return this.http.get(environment.apiChatUrl + 'groups.list', this.options); - } - - getAllUsers() { - return this.http.get(environment.apiChatUrl + 'users.list', this.options); - } - getAllConnectedUsers() { - return this.http.get(environment.apiChatUrl + 'users.presence', this.options); - } - - //Load messages from roomId - getAllDirectMessages() { - return this.http.get(environment.apiChatUrl + 'im.list', this.options); - } - //Load messages from roomId - getRoomMessages(roomId: any) { - - let params = new HttpParams(); - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params, - } - return this.http.get(environment.apiChatUrl + 'im.history', opts); - } - - sendMessage(body: any) { - let opts = { - headers: this.headers, - } - return this.http.post(environment.apiChatUrl + 'chat.sendMessage', body, opts); - } - - uploadFile(formData: any, rid: string) { - let url = environment.apiChatUrl + 'rooms.upload/' + rid; - let opts = { - headers: this.headers, - } - return this.http.post(url, formData, opts); - } - - deleteMessage(body: any) { - let opts = { - headers: this.headers, - } - return this.http.post(environment.apiChatUrl + 'chat.delete', body, opts); - } - - leaveRoom(body: any) { - let opts = { - headers: this.headers, - } - return this.http.post(environment.apiChatUrl + 'rooms.leave', body, opts); - } - //Load members from a chat - getMembers(roomId: any) { - - let params = new HttpParams(); - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'im.members', opts); - } - - getMemberInfo(userId: string) { - let params = new HttpParams(); - params = params.set("userId", userId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'users.info', opts); - } - - setUserStatus(body: any) { - let opts = { - headers: this.headers, - } - return this.http.post(environment.apiChatUrl + 'users.setStatus', body, this.options); - } - - removeChatRoom(body: any) { - let opts = { - headers: this.headers, - } - return this.http.post(environment.apiChatUrl + 'im.delete', body, this.options); - } - - createRoom(body: any) { - return this.http.post(environment.apiChatUrl + 'im.create', body, this.options); - } - getDirectMessage(roomId: string) { - let params = new HttpParams(); - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'im.messages', opts); - } - - /* GROUPS */ - addGroup(body: any) { - - return this.http.post(environment.apiChatUrl + 'groups.create', body, this.options); - } - setGroupCustomFields(body: any) { - return this.http.post(environment.apiChatUrl + 'groups.setCustomFields', body, this.options); - } - - getGroupMembers(roomId: string) { - let params = new HttpParams(); - let url = environment.apiChatUrl + 'groups.members'; - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(url, opts); - } - - getChannelMembers(roomId: string) { - let params = new HttpParams(); - let url = environment.apiChatUrl + 'channels.members'; - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(url, opts); - } - /* GROUP MESSAGES */ - getPrivateGroupMessages(roomId: any) { - - let params = new HttpParams(); - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'groups.history', opts); - } - getPublicGroupMessages(roomId: any) { - let params = new HttpParams(); - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'channels.history', opts); - } - closeGroup(body: any) { - return this.http.post(environment.apiChatUrl + 'groups.close', body, this.options); - } - closeChannel(body: any) { - return this.http.post(environment.apiChatUrl + 'channels.close', body, this.options); - } - leaveGroup(body: any) { - return this.http.post(environment.apiChatUrl + 'groups.leave', body, this.options); - } - leaveChannel(body: any) { - return this.http.post(environment.apiChatUrl + 'channels.leave', body, this.options); - } - removeChannelMember(body: any) { - let opts = { - headers: this.headers, - } - return this.http.post(environment.apiChatUrl + 'channels.kick', body, opts); - } - - addChannelOwner(body: any) { - return this.http.post(environment.apiChatUrl + 'channels.addOwner', body, this.options); - } - - addGroupOwner(body: any) { - return this.http.post(environment.apiChatUrl + 'groups.addOwner', body, this.options); - } - - deleteGroup(body: any) { - return this.http.post(environment.apiChatUrl + 'groups.delete', body, this.options); - } - - deleteChannel(body: any) { - return this.http.post(environment.apiChatUrl + 'channels.delete', body, this.options); - } - addUserToGroup(body: any) { - return this.http.post(environment.apiChatUrl + 'groups.invite', body, this.options); - } - getGroupInfo(roomId: any) { - let params = new HttpParams(); - params = params.set("roomId", roomId); - - let opts = { - headers: this.headers, - params: params - } - return this.http.get(environment.apiChatUrl + 'groups.info', opts); - } - renameGroup(body: any) { - return this.http.post(environment.apiChatUrl + 'groups.rename', body, this.options); - } - removeGroupMember(body: any) { - let opts = { - headers: this.headers, - } - return this.http.post(environment.apiChatUrl + 'groups.kick', body, opts); - } - - async subscribe(roomId: any) { - - let params = new HttpParams(); - params = params.set("roomId", roomId); - let opts = { - headers: this.headers, - params: params - } - - this.http.get(environment.apiChatUrl + 'im.messages', opts).subscribe(async res => { - - - if (res == 502) { - // Connection timeout - // happens when the connection was pending for too long - // let's reconnect - await this.subscribe(roomId); - } else if (res != 200) { - // Show Error - //showMessage(response.statusText); - this.getRoomMessages(roomId) - // Reconnect in one second - await new Promise(resolve => setTimeout(resolve, 1000)).catch ((error) => { - console.error(error); - }); - await this.subscribe(roomId); - } else { - // Got message - //let message = await response.text(); - this.getRoomMessages(roomId) - await this.subscribe(roomId); - } - - }) - - - } - - setheader() { - try { - - if (this.p.userPermission(this.p.permissionList.Chat.access) && SessionStore.user.ChatData) { - this.headers = new HttpHeaders();; - - if (this.p.userPermission(this.p.permissionList.Chat.access)) { - // - this.headers = this.headers.set('X-User-Id', SessionStore.user.ChatData.data.userId); - this.headers = this.headers.set('X-Auth-Token', SessionStore.user.ChatData.data.authToken); - this.options = { - headers: this.headers, - }; - - this.resetTimer(); - } - } - } catch (error) { - - } - } - - async refreshtoken() { - - } - - - lastUpdateIs10sAgo() { - const currentTime: any = new Date(); - - const diffTime = Math.abs(currentTime - this.timerEventTriggerDateLastUpdate); - - if(this.timerEventTriggerDateLastUpdate == null) { - return true - } - - if(diffTime >= 5000) { - return true - } - - return false - - } - - functionTimer = null; - timerEventTriggerDate = null - timerEventTriggerDateLastUpdate = null - - resetTimer() { - clearTimeout(this.functionTimer); - this.timerEventTriggerDate = new Date(+new Date() + 60000*15); - - this.functionTimer = setTimeout(() => { - - if(this.NetworkServiceService.getCurrentNetworkStatus() == ConnectionStatus.Online) { - this.refreshtoken(); - } else { - this.resetTimer() - } - - }, 60000 * 15); // time is in milliseconds - - } - -} diff --git a/src/app/services/functions/time.service.ts b/src/app/services/functions/time.service.ts index 114b13b42..ed519b8d3 100644 --- a/src/app/services/functions/time.service.ts +++ b/src/app/services/functions/time.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core'; -import { ChatService } from '../chat.service'; // import { ChatSystemService } from '../chat/chat-system.service'; @Injectable({ diff --git a/src/app/services/notifications.service.ts b/src/app/services/notifications.service.ts index ef75f94e7..853a595c7 100644 --- a/src/app/services/notifications.service.ts +++ b/src/app/services/notifications.service.ts @@ -14,7 +14,6 @@ import { notificationObject } from '../models/notifications'; import { Capacitor } from '@capacitor/core'; import { AngularFireMessaging } from '@angular/fire/messaging'; import { NotificationHolderService } from 'src/app/store/notification-holder.service'; -import { ChatService } from 'src/app/services/chat.service'; import { FCM } from '@capacitor-community/fcm'; // import { ChatSystemService } from './chat/chat-system.service'; diff --git a/src/app/shared/publication/new-publication/new-publication.page.ts b/src/app/shared/publication/new-publication/new-publication.page.ts index 59b4df286..5ae23c384 100644 --- a/src/app/shared/publication/new-publication/new-publication.page.ts +++ b/src/app/shared/publication/new-publication/new-publication.page.ts @@ -15,8 +15,6 @@ import { MiddlewareServiceService } from "src/app/shared/API/middleware/middlewa import { LakefsRepositoryService } from '../../repository/lakefs/lakefs-repository.service'; import { SocketConnectionMCRService } from "src/app/services/socket-connection-mcr.service" -import { CMAPIService } from '../../repository/CMAPI/cmapi.service'; -import { environment } from 'src/environments/environment'; import { CaptureImageOptions, MediaCapture } from '@awesome-cordova-plugins/media-capture/ngx'; import { Directory, Filesystem, FilesystemDirectory } from '@capacitor/filesystem'; import { ModalController, Platform } from '@ionic/angular'; diff --git a/src/app/store/chat/chat-message.service.spec.ts b/src/app/store/chat/chat-message.service.spec.ts deleted file mode 100644 index 3f2176442..000000000 --- a/src/app/store/chat/chat-message.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { ChatMessageService } from './chat-message.service'; - -describe('ChatMessageService', () => { - let service: ChatMessageService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(ChatMessageService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/store/chat/chat-message.service.ts b/src/app/store/chat/chat-message.service.ts deleted file mode 100644 index 9a735b745..000000000 --- a/src/app/store/chat/chat-message.service.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Injectable } from '@angular/core'; -import { localstoreService } from '../localstore.service' -import { SHA1 } from 'crypto-js' - -@Injectable({ - providedIn: 'root' -}) -export class ChatMessageService { - - private _message = [] - // local storage keyName - private keyName: string; - - constructor() { - - this.keyName = (SHA1('chat'+"ChatMessageService")).toString() - - setTimeout(()=> { - let restore = localstoreService.get(this.keyName, {}) - this._message = restore.message || {} - }, 10) - - } - - get message() { - return this._message - } - - getMessages(roomId) { - return this._message[roomId] || [] - } - - add(roomId:string, message: any[]) { - this._message[roomId] = message - - setTimeout(()=> { - localstoreService.set(this.keyName, { - message: this._message - }) - }, 10) - } - -} - - -export const ChatMessageStore = new ChatMessageService() \ No newline at end of file diff --git a/src/app/store/chat/chat-user.service.spec.ts b/src/app/store/chat/chat-user.service.spec.ts deleted file mode 100644 index 089b979cf..000000000 --- a/src/app/store/chat/chat-user.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { ChatUserService } from './chat-user.service'; - -describe('ChatUserService', () => { - let service: ChatUserService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(ChatUserService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/store/chat/chat-user.service.ts b/src/app/store/chat/chat-user.service.ts deleted file mode 100644 index 4cc442a78..000000000 --- a/src/app/store/chat/chat-user.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from '@angular/core'; -import { localstoreService } from '../localstore.service'; -import { SHA1 } from 'crypto-js'; - -@Injectable({ - providedIn: 'root' -}) -export class ChatUserService { - - // main data - private _userList = {} - // local storage keyName - private keyName: string; - - constructor() { - - this.keyName = (SHA1('chat'+"ToDayEventStorageService")).toString() - - setTimeout(()=> { - let restore = localstoreService.get(this.keyName, {}) - this._userList = restore.userList || {} - }, 10) - - } - - get userList() { - return this._userList - } - - add(roomId:string, userList: any[] = []) { - - this._userList[roomId] = userList - - this.save() - } - - private save() { - setTimeout(()=> { - localstoreService.set(this.keyName, { - userList: this._userList - }) - }, 10) - } -} - - -export const ChatUserStorage = new ChatUserService() diff --git a/src/app/ui/chat/chat.page.ts b/src/app/ui/chat/chat.page.ts index 21f44c978..7072a79f8 100644 --- a/src/app/ui/chat/chat.page.ts +++ b/src/app/ui/chat/chat.page.ts @@ -3,7 +3,6 @@ import { OnInit, } from '@angular/core'; import { ModalController } from '@ionic/angular'; -import { ChatService } from 'src/app/services/chat.service'; import { GroupMessagesPage } from './modal/group-messages/group-messages.page'; import { ContactsPage } from './modal/./messages/contacts/contacts.page'; import { MessagesPage } from './modal/./messages/messages.page'; @@ -54,7 +53,6 @@ export class ChatPage implements OnInit { items$!: DexieObservable; constructor( - private chatService: ChatService, private modalController: ModalController, private timeService: TimeService, public ThemeService: ThemeService, @@ -188,9 +186,7 @@ export class ChatPage implements OnInit { message: '', status: status, } - this.chatService.setUserStatus(body).subscribe(res => { - }) } hideRefreshButton() { diff --git a/src/app/ui/chat/component/edit-group/edit-group.page.ts b/src/app/ui/chat/component/edit-group/edit-group.page.ts index 625d92ec3..5421d01eb 100644 --- a/src/app/ui/chat/component/edit-group/edit-group.page.ts +++ b/src/app/ui/chat/component/edit-group/edit-group.page.ts @@ -1,7 +1,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { ModalController, PickerController } from '@ionic/angular'; -import { ChatService } from 'src/app/services/chat.service'; import { ThemeService } from 'src/app/services/theme.service' import { SessionStore } from 'src/app/store/session.service'; import { HttpResponse } from '@microsoft/signalr'; @@ -33,7 +32,6 @@ export class EditGroupPage implements OnInit { constructor( private modalController: ModalController, private pickerController: PickerController, - private chatService: ChatService, public ThemeService: ThemeService, private RoomRepositoryService: RoomRepositoryService, private httpErrorHandle: HttpErrorHandle, @@ -48,16 +46,16 @@ export class EditGroupPage implements OnInit { } getRoomInfo(){ - this.chatService.getRoomInfo(this.roomId).subscribe(room=>{ - this.room = room['room']; + // this.chatService.getRoomInfo(this.roomId).subscribe(room=>{ + // this.room = room['room']; - try { - this.groupName = this.room.name.split('-').join(' '); - } catch (error) { - this.groupName = this.room.name; - } + // try { + // this.groupName = this.room.name.split('-').join(' '); + // } catch (error) { + // this.groupName = this.room.name; + // } - }); + // }); } close() { @@ -93,11 +91,11 @@ export class EditGroupPage implements OnInit { updateGroup() { this.showLoader = true; - this.chatService.getRoomInfo(this.roomId).subscribe(room=>{ - this.room = room['room']; - this.showLoader = false; - this.openGroupMessage.emit(this.room._id); - }); + // this.chatService.getRoomInfo(this.roomId).subscribe(room=>{ + // this.room = room['room']; + // this.showLoader = false; + // this.openGroupMessage.emit(this.room._id); + // }); } _ionChange(event){ diff --git a/src/app/ui/chat/component/group-messages/group-messages.page.ts b/src/app/ui/chat/component/group-messages/group-messages.page.ts index ac399f5de..410c87744 100644 --- a/src/app/ui/chat/component/group-messages/group-messages.page.ts +++ b/src/app/ui/chat/component/group-messages/group-messages.page.ts @@ -1,7 +1,6 @@ import { Component, OnChanges, OnInit, Input, SimpleChanges, Output, EventEmitter, ViewChild, ElementRef, AfterViewInit, OnDestroy } from '@angular/core'; import { AnimationController, ModalController, PopoverController, Platform } from '@ionic/angular'; import { AlertService } from 'src/app/services/alert.service'; -import { ChatService } from 'src/app/services/chat.service'; import { GroupContactsPage } from './group-contacts/group-contacts.page'; import { ChatOptionsFeaturesPage } from 'src/app/modals/chat-options-features/chat-options-features.page'; import { TimeService } from 'src/app/services/functions/time.service'; @@ -87,7 +86,6 @@ export class GroupMessagesPage implements OnInit, OnChanges, AfterViewInit, OnDe // public ChatSystemService: ChatSystemService, private modalController: ModalController, public popoverController: PopoverController, - private chatService: ChatService, private animationController: AnimationController, private alertService: AlertService, private timeService: TimeService, @@ -156,9 +154,6 @@ export class GroupMessagesPage implements OnInit, OnChanges, AfterViewInit, OnDe message: '', status: status, } - this.chatService.setUserStatus(body).subscribe(res => { - // - }) } scrollToBottom(): void { diff --git a/src/app/ui/chat/component/messages/messages.page.html b/src/app/ui/chat/component/messages/messages.page.html index 399c017eb..d18b6d8e3 100644 --- a/src/app/ui/chat/component/messages/messages.page.html +++ b/src/app/ui/chat/component/messages/messages.page.html @@ -1,9 +1,9 @@ -
+
- {{ roomData.roomName }} + {{ roomData.roomName }}
@@ -44,7 +44,7 @@
@@ -67,7 +67,10 @@
- +
diff --git a/src/app/ui/chat/component/messages/messages.page.ts b/src/app/ui/chat/component/messages/messages.page.ts index b386368b2..9d83e219b 100644 --- a/src/app/ui/chat/component/messages/messages.page.ts +++ b/src/app/ui/chat/component/messages/messages.page.ts @@ -3,8 +3,6 @@ import { AnimationController, GestureController, IonRange, ModalController, Popo import { ToastService } from 'src/app/services/toast.service'; 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'; -import { ChatUserStorage } from 'src/app/store/chat/chat-user.service'; import { TimeService } from 'src/app/services/functions/time.service'; import { FileService } from 'src/app/services/functions/file.service'; import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page'; @@ -43,6 +41,7 @@ import { allowedDocExtension } from 'src/app/utils/allowedDocExtension'; import { SpeakerService, StartRecordingResultError, StopRecordingResultError } from 'src/app/infra/speaker/speaker.service' import { compressImageBase64 } from 'src/app/utils/imageCompressore'; import { ChatPopoverPage } from '../../modal/chat-popover/chat-popover.page'; +import { LastMessage } from '../../utils/lastMessage'; @Component({ selector: 'app-messages', @@ -72,10 +71,6 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy @Output() getGroups: EventEmitter = new EventEmitter(); - - chatMessageStore = ChatMessageStore - chatUserStorage = ChatUserStorage - scrollingOnce: boolean = true; private scrollChangeCallback: () => void; currentPosition: any; @@ -176,13 +171,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy this.listenToUpdateMessage(); this.listenToSendMessage() - this.roomMessage$ = this.messageRepositoryService.getItemsLive(this.roomId) + // 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) - this.messageRepositoryService.listAllMessagesByRoomId(this.roomId).then(()=> { - // this.getMessages(); - }) this.userTypingServiceRepository.getUserTypingLive().subscribe((e) => { const arrayNames = e.map(e => e.userName) @@ -202,11 +194,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy this.messages1[this.roomId] = [] this.messages1[this.roomId] = messages - this.loadAttachment() + + this.messages1[this.roomId].push(LastMessage) - setTimeout(() => { - this.scrollToBottomClicked() - }, 200) + this.loadAttachment() } @@ -214,33 +205,32 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy for(const message of this.messages1[this.roomId]) { if(message.hasAttachment) { - const result = await this.chatServiceService.getMessageAttachmentByMessageId({ - $messageId: message.$id, - id: message.attachments[0].id - }) - - if(result.isOk()){ - message.attachments[0].safeFile = result.value - } + if(message.$id) { + console.log('message.$id', message.$id) + this.chatServiceService.getMessageAttachmentByMessageId(message).then((result)=> { + if(result.isOk()) { + message.attachments[0].safeFile = result.value + } + }) + } + } - } } - // Sorting function - sortBySentAt (arr, order = 'asc') { - return arr.sort((a, b) => { - // Handle null or undefined sentAt - const dateA = a.sentAt ? new Date(a.sentAt).getTime() : Number.MAX_VALUE; - const dateB = b.sentAt ? new Date(b.sentAt).getTime() : Number.MAX_VALUE; + async onImageLoad(message: MessageEntity, index:number) { + if(message.attachments[0].fileName == LastMessage.attachments[0].fileName) { - if (order === 'asc') { - return dateA - dateB; - } else { - return dateB - dateA; - } - }); - }; + this.scrollToBottom() + setTimeout(() => { + this.scrollToBottom(); + }, 100) + + this.messages1[this.roomId].splice(index, 1); + } + } + + async onImageError() {} listenToIncomingMessage() { @@ -404,14 +394,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy } ngOnInit() { - // this.ChatSystemService.getAllRooms(); - // this.chatService.refreshtoken(); this.scrollToBottom(); this.getChatMembers(); this.deleteRecording(); - // this.loadFiles(); - } diff --git a/src/app/ui/chat/modal/chat-popover/chat-popover.page.ts b/src/app/ui/chat/modal/chat-popover/chat-popover.page.ts index 02307aedc..0b5765ed9 100644 --- a/src/app/ui/chat/modal/chat-popover/chat-popover.page.ts +++ b/src/app/ui/chat/modal/chat-popover/chat-popover.page.ts @@ -1,6 +1,5 @@ import { Component, OnInit } from '@angular/core'; import { ModalController, NavParams, PopoverController } from '@ionic/angular'; -import { ChatService } from 'src/app/services/chat.service'; import { ToastService } from 'src/app/services/toast.service'; import { ThemeService } from 'src/app/services/theme.service' import { SetRoomOwnerPage } from 'src/app/modals/set-room-owner/set-room-owner.page'; diff --git a/src/app/ui/chat/modal/edit-group/edit-group.page.ts b/src/app/ui/chat/modal/edit-group/edit-group.page.ts index bd2bd94b0..5ac98c026 100644 --- a/src/app/ui/chat/modal/edit-group/edit-group.page.ts +++ b/src/app/ui/chat/modal/edit-group/edit-group.page.ts @@ -1,7 +1,6 @@ import { HttpErrorResponse } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { ModalController, NavParams, PickerController } from '@ionic/angular'; -import { ChatService } from 'src/app/services/chat.service'; import { ThemeService } from 'src/app/services/theme.service' @Component({ @@ -21,7 +20,6 @@ export class EditGroupPage implements OnInit { constructor( private modalController: ModalController, private pickerController: PickerController, - private chatService: ChatService, private navParams: NavParams, public ThemeService: ThemeService ) { @@ -34,16 +32,7 @@ export class EditGroupPage implements OnInit { } getRoomInfo(){ - this.chatService.getRoomInfo(this.roomId).subscribe(room=>{ - this.room = room['room']; - - try { - this.groupName = this.room.name.split('-').join(' '); - } catch(error) { - this.groupName = this.room.name; - } - - }); + } close(){ @@ -57,13 +46,10 @@ export class EditGroupPage implements OnInit { "roomId": this.room._id, "name": name, } - this.chatService.renameGroup(body).subscribe(res=>{ - this.modalController.dismiss(res['group']); - }); } else{ - - } + + } } _ionChange(event){ this.showDuration = event.detail.checked; @@ -72,42 +58,42 @@ export class EditGroupPage implements OnInit { const picker = await this.pickerController.create({ cssClass: '', buttons: [ - { + { text: 'Cancelar', role: 'cancel', cssClass: 'btn-cancel' }, - { - text: 'Ok', + { + text: 'Ok', cssClass: 'btn-cancel', handler:(value:any)=>{ - + this.selectedDuration = [ value.days.value, value.hours.value, value.minutes.value, ] - + if(value.days.value != null && value.hours.value != null && value.minutes.value != null){ if(value.days.value > 0){ if(value.days.value == 1){ if(value.hours.value == 1){ - this.displayDuration = value.days.value + " day " + + this.displayDuration = value.days.value + " day " + value.hours.value + " hora " + value.minutes.value + " minutos"; } else{ - this.displayDuration = value.days.value + " days " + + this.displayDuration = value.days.value + " days " + value.hours.value + " horas " + value.minutes.value + " minutos"; } } else{ if(value.hours.value == 1){ - this.displayDuration = value.days.value + " days " + + this.displayDuration = value.days.value + " days " + value.hours.value + " hora " + value.minutes.value + " minutos"; } else{ - this.displayDuration = value.days.value + " days " + + this.displayDuration = value.days.value + " days " + value.hours.value + " horas " + value.minutes.value + " minutos"; } @@ -123,7 +109,7 @@ export class EditGroupPage implements OnInit { value.minutes.value + " minutos"; } } - } + } }, }, ], @@ -176,7 +162,7 @@ export class EditGroupPage implements OnInit { await picker.present(); picker.onDidDismiss().then(async data =>{ let day = await picker.getColumn('days'); - let hour = await picker.getColumn('hours'); + let hour = await picker.getColumn('hours'); let minutes = await picker.getColumn('minutes'); }); diff --git a/src/app/ui/chat/modal/group-messages/group-contacts/group-contacts.page.ts b/src/app/ui/chat/modal/group-messages/group-contacts/group-contacts.page.ts index 9494a6169..9f8082330 100644 --- a/src/app/ui/chat/modal/group-messages/group-contacts/group-contacts.page.ts +++ b/src/app/ui/chat/modal/group-messages/group-contacts/group-contacts.page.ts @@ -3,7 +3,6 @@ import { Component, OnInit } from '@angular/core'; import { ModalController, NavParams } from '@ionic/angular'; import * as _ from 'lodash'; import { AuthService } from 'src/app/services/auth.service'; -import { ChatService } from 'src/app/services/chat.service'; import { GroupMessagesPage } from '../group-messages.page'; import { ThemeService } from 'src/app/services/theme.service' import { SessionStore } from 'src/app/store/session.service'; @@ -39,10 +38,6 @@ export class GroupContactsPage implements OnInit { constructor( private modalController: ModalController, - private http: HttpClient, - private chatService: ChatService, - private authService: AuthService, - private navParams: NavParams, public ThemeService: ThemeService, // public ChatSystemService: ChatSystemService, ) @@ -122,18 +117,7 @@ export class GroupContactsPage implements OnInit { } getMembers(){ - if(this.room.t == "p"){ - this.chatService.getGroupMembers(this.room._id).subscribe(res=>{ - this.members = res['members']; - this.loadUsers(); - }); - } - else if(this.room.t == "c"){ - this.chatService.getChannelMembers(this.room._id).subscribe(res=>{ - this.members = res['members']; - this.loadUsers(); - }); - } + } separateLetter(record, recordIndex, records){ @@ -157,16 +141,10 @@ export class GroupContactsPage implements OnInit { } if(this.room.t == "p"){ - this.chatService.removeGroupMember(body).subscribe(res=>{ - this.getMembers(); - }); } else if(this.room.t == "c"){ - this.chatService.removeChannelMember(body).subscribe(res=>{ - this.getMembers(); - }); } } @@ -262,9 +240,7 @@ export class GroupContactsPage implements OnInit { "userId":user._id, } - this.chatService.addUserToGroup(body).subscribe(res=>{ - }); }); } @@ -277,14 +253,7 @@ export class GroupContactsPage implements OnInit { this.loading = true console.log('this.room', this.room) - this.chatService.getRoomInfo(this.room._id).subscribe(room=>{ - this.room = room['room']; - this.addContacts(this.room); - this.openGroupMessages(room['room']._id); - this.loading = false - }, ()=> { - this.loading = false - }); + } async openGroupMessages(roomId:any){ diff --git a/src/app/ui/chat/modal/group-messages/group-messages.page.ts b/src/app/ui/chat/modal/group-messages/group-messages.page.ts index dad76e49b..8c998de43 100644 --- a/src/app/ui/chat/modal/group-messages/group-messages.page.ts +++ b/src/app/ui/chat/modal/group-messages/group-messages.page.ts @@ -1,7 +1,6 @@ import { Component, ElementRef, OnInit, ViewChild, AfterViewInit, OnDestroy, ChangeDetectorRef, } from '@angular/core'; import { ModalController, NavParams, PopoverController, Platform } from '@ionic/angular'; import { AlertService } from 'src/app/services/alert.service'; -import { ChatService } from 'src/app/services/chat.service'; import { GroupContactsPage } from './group-contacts/group-contacts.page'; import { Router } from '@angular/router' import { EditGroupPage } from '../edit-group/edit-group.page'; @@ -13,7 +12,6 @@ import { EventPerson } from 'src/app/models/eventperson.model'; 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 { ChatSystemService } from 'src/app/services/chat/chat-system.service'; import { FileType } from 'src/app/models/fileType'; import { Storage } from '@ionic/storage'; @@ -32,7 +30,6 @@ import { RouteService } from 'src/app/services/route.service'; import { FileValidatorService } from "src/app/services/file/file-validator.service" import { sanitize } from "sanitize-filename-ts"; import { FilePicker } from '@capawesome/capacitor-file-picker'; -import { ViewDocumentSecondOptionsPage } from 'src/app/modals/view-document-second-options/view-document-second-options.page'; import { NewEventPage } from 'src/app/pages/agenda/new-event/new-event.page'; import { ChatPopoverPage } from '../chat-popover/chat-popover.page'; import { ChatOptionsPopoverPage } from '../chat-options-popover/chat-options-popover.page'; @@ -91,10 +88,6 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy { constructor( private modalController: ModalController, public popoverController: PopoverController, - private chatService: ChatService, - private navParams: NavParams, - private alertService: AlertService, - private route: Router, private timeService: TimeService, private fileService: FileService, private toastService: ToastService, @@ -103,7 +96,6 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy { private platform: Platform, //public ChatSystemService: ChatSystemService, private storage: Storage, - private CameraService: CameraService, private sanitiser: DomSanitizer, private file: File, private fileOpener: FileOpener, @@ -1054,43 +1046,7 @@ export class GroupMessagesPage implements OnInit, AfterViewInit, OnDestroy { } async serverLongPull() { - this.chatService.getPrivateGroupMessages(this.roomId).subscribe(async res => { - if (res == 502) { - // Connection timeout - // happens when the connection was pending for too long - // let's reconnect - await this.serverLongPull(); - } else if (res != 200) { - // Show Error - //showMessage(response.statusText); - //this.loadMessages() - let msgOnly = res['messages'].filter(data => data.t != 'au'); - //this.messages = msgOnly.reverse(); - // - this.transformDataMSG(msgOnly.reverse()); - // this.getRoomMessageDB(this.roomId); - // Reconnect in one second - if (this.route.url != "/home/chat") { - - } else { - //Check if modal is opened - if (document.querySelector('.isGroupChatOpened')) { - await new Promise(resolve => setTimeout(resolve, 5000)).catch((error) => { - console.error(error); - }); - await this.serverLongPull(); - - } - } - - } else { - // Got message - //let message = await response.text(); - //this.loadMessages() - await this.serverLongPull(); - } - }); } sliderOpts = { diff --git a/src/app/ui/chat/modal/messages-options/messages-options.page.ts b/src/app/ui/chat/modal/messages-options/messages-options.page.ts index bcd0b7861..e51dc99a3 100644 --- a/src/app/ui/chat/modal/messages-options/messages-options.page.ts +++ b/src/app/ui/chat/modal/messages-options/messages-options.page.ts @@ -1,6 +1,5 @@ import { Component, OnInit } from '@angular/core'; import { ModalController, NavParams, PopoverController } from '@ionic/angular'; -import { ChatService } from 'src/app/services/chat.service'; import { ThemeService } from 'src/app/services/theme.service'; @Component({ @@ -15,7 +14,6 @@ export class MessagesOptionsPage implements OnInit { constructor( private popoverController: PopoverController, private modalController: ModalController, - private chatService: ChatService, private navParams: NavParams, public ThemeService: ThemeService, ) @@ -40,9 +38,6 @@ export class MessagesOptionsPage implements OnInit { closeChatRoom(){ let body = { "roomId": this.roomId } - this.chatService.removeChatRoom(body).subscribe(res=>{ - - }); this.close(); } diff --git a/src/app/ui/chat/modal/messages/contacts/contacts.page.ts b/src/app/ui/chat/modal/messages/contacts/contacts.page.ts index 4cccbdbbf..057e32318 100644 --- a/src/app/ui/chat/modal/messages/contacts/contacts.page.ts +++ b/src/app/ui/chat/modal/messages/contacts/contacts.page.ts @@ -1,7 +1,5 @@ import { Component, OnInit } from '@angular/core'; import { ModalController } from '@ionic/angular'; -import { ChatService } from 'src/app/services/chat.service'; -import { MessagesPage } from '../messages.page'; import { ThemeService } from 'src/app/services/theme.service' import { SessionStore } from 'src/app/store/session.service'; import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service'; @@ -9,8 +7,7 @@ import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room- 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', @@ -38,7 +35,6 @@ export class ContactsPage implements OnInit { constructor( private modalController: ModalController, - private chatService: ChatService, public ThemeService: ThemeService, private contactsRepositoryService: ContactRepositoryService, private RoomRepositoryService: RoomRepositoryService, diff --git a/src/app/ui/chat/modal/messages/messages.page.html b/src/app/ui/chat/modal/messages/messages.page.html index bcbb86b06..6540f9fe2 100644 --- a/src/app/ui/chat/modal/messages/messages.page.html +++ b/src/app/ui/chat/modal/messages/messages.page.html @@ -9,8 +9,8 @@
-
- {{ roomData.roomName }} +
+ {{ roomData.roomName }}
diff --git a/src/app/ui/chat/modal/messages/messages.page.ts b/src/app/ui/chat/modal/messages/messages.page.ts index 485e5b026..4907e2ef9 100644 --- a/src/app/ui/chat/modal/messages/messages.page.ts +++ b/src/app/ui/chat/modal/messages/messages.page.ts @@ -1,14 +1,11 @@ import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { GestureController, ModalController, NavParams, PopoverController, Platform } from '@ionic/angular'; import { ViewDocumentPage } from 'src/app/modals/view-document/view-document.page'; -import { EventPerson } from 'src/app/models/eventperson.model'; import { ExpedientTaskModalPageNavParamsTask } from 'src/app/models/ExpedientTaskModalPage'; import { ContactsPage } from 'src/app/ui/chat/modal/messages/contacts/contacts.page'; import { AlertService } from 'src/app/services/alert.service'; import { FileService } from 'src/app/services/functions/file.service'; import { ToastService } from 'src/app/services/toast.service'; -import { ChatMessageStore } from 'src/app/store/chat/chat-message.service'; -import { ChatUserStorage } from 'src/app/store/chat/chat-user.service'; import { ThemeService } from 'src/app/services/theme.service' import { VoiceRecorder, GenericResponse } from 'capacitor-voice-recorder'; @@ -16,15 +13,11 @@ 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, CameraSource } from '@capacitor/camera'; +import { CameraResultType } 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'; -import { File } from '@awesome-cordova-plugins/file/ngx'; -import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx'; -import { Filesystem, Directory } from '@capacitor/filesystem'; -import { FileValidatorService } from "src/app/services/file/file-validator.service" -import { FilePicker } from '@capawesome/capacitor-file-picker'; + //====== import { Observable as DexieObservable } from 'Dexie'; import { Subscription } from 'rxjs'; @@ -45,7 +38,11 @@ import { RecordingData } from 'capacitor-voice-recorder'; import { Logger } from 'src/app/services/logger/main/service'; import { MessagesOptionsPage } from '../messages-options/messages-options.page'; import { ChatOptionsPopoverPage } from '../chat-options-popover/chat-options-popover.page'; - +import { CameraService } from 'src/app/infra/camera/camera.service' +import { FilePickerMobileService } from 'src/app/infra/file-picker/mobile/file-picker-mobile.service' +import { FilePickerWebService } from 'src/app/infra/file-picker/web/file-picker-web.service' +import { allowedDocExtension } from 'src/app/utils/allowedDocExtension'; +import { JSFileToDataUrl } from 'src/app/utils/ToBase64'; const IMAGE_DIR = 'stored-images'; @Component({ @@ -57,7 +54,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { showLoader: boolean; @ViewChild('scrollMe') private myScrollContainer: ElementRef; - /* @ViewChild('messageContainer') messageContainer: ElementRef; */ @ViewChild('rectangle') private rectangle: ElementRef; canvas: any @@ -70,15 +66,10 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { members: any; scrollingOnce: boolean = true; - chatMessageStore = ChatMessageStore; - chatUserStorage = ChatUserStorage; - private scrollChangeCallback: () => void; currentPosition: any; startPosition: number; scrollToBottomBtn = false; - attendees: EventPerson[] = []; - longPressActive = false; showMessageOptions = false; selectedMsgId: string; @@ -146,14 +137,14 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { private platform: Platform, private storage: Storage, private sanitiser: DomSanitizer, - private file: File, - private fileOpener: FileOpener, - private FileValidatorService: FileValidatorService, private roomRepositoryService: RoomRepositoryService, private messageRepositoryService: MessageRepositoryService, private userTypingServiceRepository: UserTypingServiceRepository, private chatServiceService: ChatServiceService, private FilePickerService: FilePickerService, + private CameraService: CameraService, + private FilePickerMobileService: FilePickerMobileService, + private FilePickerWebService: FilePickerWebService ) { @@ -169,23 +160,10 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { this.listenToSendMessage() - this.roomMessage$ = this.messageRepositoryService.getItemsLive(this.roomId) + // 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) - - this.newMessagesStream?.unsubscribe() - this.newMessagesStream = this.messageRepositoryService.subscribeToNewMessages(this.roomId).subscribe((e) => { - - setTimeout(() => { - this.scrollToBottomClicked() - }, 200) - - setTimeout(() => { - this.scrollToBottomClicked() - }, 500) - - }) + // this.roomRepositoryService.getRoomById(this.roomId) this.userTypingServiceRepository.getUserTypingLive().subscribe((e) => { const arrayNames = e.map(e => e.userName) @@ -218,10 +196,8 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { for(const message of this.messages1[this.roomId]) { if(message.hasAttachment) { - const result = await this.chatServiceService.getMessageAttachmentByMessageId({ - $messageId: message.$id, - id: message.attachments[0].id - }) + + const result = await this.chatServiceService.getMessageAttachmentByMessageId(message) if(result.isOk()) { @@ -282,14 +258,11 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { listenToIncomingMessage() { this.messageReceiveSubject?.unsubscribe(); this.messageReceiveSubject = this.chatServiceService.listenToIncomingMessage(this.roomId).subscribe(async (message) => { - this.messages1[this.roomId].push(message as MessageEntity) + this.messages1[this.roomId].unshift(message as MessageEntity) if(message.hasAttachment) { - const result = await this.chatServiceService.getMessageAttachmentByMessageId({ - $messageId: message.$id, - id: message.attachments[0].id - }) + const result = await this.chatServiceService.getMessageAttachmentByMessageId(message) if(result.isOk()) { @@ -734,33 +707,48 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { async takePictureMobile() { - this.addFileToChatMobile() + const picture = await this.CameraService.takePicture({ + cameraResultType: CameraResultType.DataUrl, + quality: 90 + }) + if(picture.isOk()) { + const file = picture.value - } + const compressedImage = await compressImageBase64( + file.dataUrl, + 800, // maxWidth + 800, // maxHeight + 0.9 // quality + ) - dataURItoBlob(dataURI) { - // convert base64 to raw binary data held in a string - // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this - var byteString = atob(dataURI.split(',')[1]); + if(compressedImage.isOk()) { - // separate out the mime component - var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] + const message = new MessageEntity(); + message.roomId = this.roomId - // write the bytes of the string to an ArrayBuffer - var ab = new ArrayBuffer(byteString.length); + message.sender = { + userPhoto: '', + wxeMail: SessionStore.user.Email, + wxFullName: SessionStore.user.FullName, + wxUserId: SessionStore.user.UserId + } - // create a view into the buffer - var ia = new Uint8Array(ab); + 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) + + } - // set the bytes of the buffer to the correct values - for (var i = 0; i < byteString.length; i++) { - ia[i] = byteString.charCodeAt(i); } - // write the ArrayBuffer to a blob, and you're done - var blob = new Blob([ab], { type: mimeString }); - return blob; } @@ -856,6 +844,9 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { } } else { + if(file.error.type == 'PERMISSION_DENIED') { + this.toastService._badRequest("Sem acesso a camera") + } Logger.error('failed to pick picture from the device', { error: file.error }) @@ -863,79 +854,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { } - 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"]; - return zoneOriginalInstance || fileReader; - } - - - _getBase64(file) { - return new Promise((resolve, reject) => { - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function () { - resolve(reader.result) - }; - reader.onerror = function (error) { - console.log('Error: ', error); - }; - }) - } async addFileToChat(types) { console.log('add file ') @@ -944,100 +862,90 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { if (this.platform.is('ios')) { console.log('ios add file ') - const resultt = await FilePicker.pickFiles({ + const result = await this.FilePickerMobileService.getFile({ types: ['application/pdf', 'application/doc', 'application/docx','application/xls', 'application/xlsx', 'application/ppt', 'application/pptx', 'application/txt'], multiple: false, readData: true, - }); + }) - console.log('RESULT', resultt.files[0].data) + if(result.isOk()) { + console.log('RESULT', result.value.files[0].data) - const message = new MessageEntity(); - message.roomId = this.roomId + const message = new MessageEntity(); + message.roomId = this.roomId - message.sender = { - userPhoto: '', - wxeMail: SessionStore.user.Email, - wxFullName: SessionStore.user.FullName, - wxUserId: SessionStore.user.UserId + message.sender = { + userPhoto: '', + wxeMail: SessionStore.user.Email, + wxFullName: SessionStore.user.FullName, + wxUserId: SessionStore.user.UserId + } + + message.attachments = [{ + file: result.value.files[0].data, + fileName: result.value.files[0].name, + source: MessageAttachmentSource.Device, + fileType: MessageAttachmentFileType.Doc + }] + + this.messages1[this.roomId].push(message) + this.chatServiceService.sendMessage(message) + + return } - message.attachments = [{ - file: resultt.files[0].data, - fileName: resultt.files[0].name, - source: MessageAttachmentSource.Device, - fileType: MessageAttachmentFileType.Doc - }] - - this.messages1[this.roomId].push(message) - this.chatServiceService.sendMessage(message) - - return } - const file = await this.fileService.getFileFromDevice(types); - console.log(file) + const file = await this.FilePickerWebService.getFileFromDevice(types) + + if(file.isOk()) { + + console.log(file) - const fileName = file.name + const fileName = file.value.name - const validation = this.FileValidatorService.fileNameValidation(fileName) + const validation = await allowedDocExtension(fileName) - if (validation.isOk) { + if (validation.isOk()) { - const encodedData = btoa(JSON.stringify(await this.getBase64(file).catch((error) => { - console.error(error); - }))); - console.log(encodedData) - const blob = this.fileService.base64toBlob(encodedData, file.type) + let fileBase64 = await JSFileToDataUrl(file.value); - const formData = new FormData(); - formData.append('blobFile', blob); + if(fileBase64.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: fileBase64.value.split(',')[1], + fileName: file.value.name, + source: MessageAttachmentSource.Device, + fileType: MessageAttachmentFileType.Doc, + mimeType: file.value.type + }] + + this.messages1[this.roomId].push(message) + this.chatServiceService.sendMessage(message) + + } - const message = new MessageEntity(); - message.roomId = this.roomId - - message.sender = { - userPhoto: '', - wxeMail: SessionStore.user.Email, - wxFullName: SessionStore.user.FullName, - wxUserId: SessionStore.user.UserId + } else { + this.toastService._badRequest("Ficheiro inválido") } - - message.attachments = [{ - file: encodedData, - fileName: file.name, - source: MessageAttachmentSource.Device, - fileType: MessageAttachmentFileType.Doc, - mimeType: file.type - }] - - this.messages1[this.roomId].push(message) - this.chatServiceService.sendMessage(message) - - } else { - this.toastService._badRequest("Ficheiro inválido") } } - getBase64(file) { - var reader = this.getFileReader(); - reader.readAsDataURL(file); - return new Promise(resolve => { - reader.onload = function () { - resolve(reader.result) - }; - reader.onerror = function (error) { - - }; - }); - - } - async openChatOptions(ev?: any) { const roomId = this.roomId @@ -1085,40 +993,6 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { } - - b64toBlob(b64Data, contentType) { - contentType = contentType || ''; - var sliceSize = 512; - b64Data = b64Data.replace(/^[^,]+,/, ''); - b64Data = b64Data.replace(/\s/g, ''); - var byteCharacters = window.atob(b64Data); - var byteArrays = []; - - for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { - var slice = byteCharacters.slice(offset, offset + sliceSize); - - var byteNumbers = new Array(slice.length); - for (var i = 0; i < slice.length; i++) { - byteNumbers[i] = slice.charCodeAt(i); - } - - var byteArray = new Uint8Array(byteNumbers); - - byteArrays.push(byteArray); - } - - var blob = new Blob(byteArrays, { type: contentType }); - return blob; - } - - blobToBase64(blob) { - return new Promise((resolve, _) => { - const reader = new FileReader(); - reader.onloadend = () => resolve(reader.result); - reader.readAsDataURL(blob); - }); - } - async openFile(pdfString, filename, type) { console.log('url while open ',pdfString) @@ -1135,43 +1009,43 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { /* await modal.present(); */ - var blob = new Blob([pdfString], { type: 'application/pdf' }); + // var blob = new Blob([pdfString], { type: 'application/pdf' }); - console.log('blob blob', blob) + // console.log('blob blob', blob) - this.blobToBase64(blob).then((value) => { - console.log(value) - }).catch((error) => { - console.log(error) - }) + // this.blobToBase64(blob).then((value) => { + // console.log(value) + // }).catch((error) => { + // console.log(error) + // }) - let pathFile = '' - const fileName = filename - if (this.platform.is('ios')) { - pathFile = this.file.documentsDirectory - } else { - pathFile = this.file.externalRootDirectory - } + // let pathFile = '' + // const fileName = filename + // if (this.platform.is('ios')) { + // pathFile = this.file.documentsDirectory + // } else { + // pathFile = this.file.externalRootDirectory + // } - console.log('file data', pdfString) - console.log(pathFile) + // console.log('file data', pdfString) + // console.log(pathFile) - let removePre = this.removeTextBeforeSlash(pdfString,',') - console.log('file data remove ', removePre) + // let removePre = this.removeTextBeforeSlash(pdfString,',') + // console.log('file data remove ', removePre) - await Filesystem.writeFile({ - path: fileName, - data: removePre, - directory: Directory.Cache, - }).then((dir) => { - console.log('DIR ', dir) - this.fileOpener - .open(dir.uri, type) - .then(() => console.log()) - .catch(e => console.error(e)) - }).catch((error) => { - console.log('error writing the file', error) - }); + // await Filesystem.writeFile({ + // path: fileName, + // data: removePre, + // directory: Directory.Cache, + // }).then((dir) => { + // console.log('DIR ', dir) + // this.fileOpener + // .open(dir.uri, type) + // .then(() => console.log()) + // .catch(e => console.error(e)) + // }).catch((error) => { + // console.log('error writing the file', error) + // }); } removeTextBeforeSlash(inputString, controlString) { @@ -1273,52 +1147,16 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy { } - async compressImageBase64(base64String: string, maxWidth: number, maxHeight: number, quality: number): Promise { - return new Promise((resolve, reject) => { - const image = new (window as any).Image(); - image.src = base64String; - - image.onload = async () => { - const canvas = document.createElement('canvas'); - let newWidth = image.width; - let newHeight = image.height; - - if (newWidth > maxWidth) { - newHeight *= maxWidth / newWidth; - newWidth = maxWidth; - } - - if (newHeight > maxHeight) { - newWidth *= maxHeight / newHeight; - newHeight = maxHeight; - } - - canvas.width = newWidth; - canvas.height = newHeight; - - const context = canvas.getContext('2d'); - context?.drawImage(image, 0, 0, newWidth, newHeight); - - const compressedBase64 = canvas.toDataURL('image/jpeg', quality); - resolve(compressedBase64); - }; - - image.onerror = (error) => { - reject(error); - }; - }); - } - - dataURItoBlobIso(dataURI: any) { - const byteString = window.atob(dataURI); - const arrayBuffer = new ArrayBuffer(byteString.length); - const int8Array = new Uint8Array(arrayBuffer); - for (let i = 0; i < byteString.length; i++) { - int8Array[i] = byteString.charCodeAt(i); - } - const blob = new Blob([int8Array], { type: 'application/pdf' }); - return blob; - } + // dataURItoBlobIso(dataURI: any) { + // const byteString = window.atob(dataURI); + // const arrayBuffer = new ArrayBuffer(byteString.length); + // const int8Array = new Uint8Array(arrayBuffer); + // for (let i = 0; i < byteString.length; i++) { + // int8Array[i] = byteString.charCodeAt(i); + // } + // const blob = new Blob([int8Array], { type: 'application/pdf' }); + // return blob; + // } messageDelete(message: MessageEntity) { diff --git a/src/app/ui/chat/utils/lastMessage.ts b/src/app/ui/chat/utils/lastMessage.ts new file mode 100644 index 000000000..0c1a4021c --- /dev/null +++ b/src/app/ui/chat/utils/lastMessage.ts @@ -0,0 +1,23 @@ +import { MessageAttachmentFileType, MessageAttachmentSource } from "src/app/module/chat/data/dto/message/messageOutputDTO"; +import { MessageEntity } from "src/app/module/chat/domain/entity/message"; +import { SessionStore } from "src/app/store/session.service"; + +export const LastMessage = new MessageEntity() + +LastMessage.sentAt = new Date().toISOString() + +LastMessage.message = 'last' +LastMessage.sender = { + userPhoto: '', + wxeMail: SessionStore.user.Email, + wxFullName: SessionStore.user.FullName, + wxUserId: SessionStore.user.UserId +} + +LastMessage.attachments = [{ + safeFile: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/wcAAwAB/BO5RfQAAAAASUVORK5CYII=', + fileName: "lastMessageUUID", + source: MessageAttachmentSource.Device, + fileType: MessageAttachmentFileType.Image, + mimeType: 'image/png', +}] \ No newline at end of file diff --git a/src/app/utils/ToBase64.ts b/src/app/utils/ToBase64.ts index f15f3ee5e..2695ef6c9 100644 --- a/src/app/utils/ToBase64.ts +++ b/src/app/utils/ToBase64.ts @@ -70,6 +70,7 @@ export function createDataURL(base64String: string, mimeType: string): string { * Converts a `Blob` to a Data URL. * @param {Blob} blob - The `Blob` to be converted. * @returns {Promise} A promise that resolves with the Data URL representation of the `Blob`. + * @example const result = 'data:audio/aac;base64,ZGF0YTphdWRpby9hYWM7YmFzZTY0…RnNRQmxmL0FGQUl' */ export function convertBlobToDataURL(blob: Blob): Promise { return new Promise((resolve, reject) => {