mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 12:37:53 +00:00
set bold
This commit is contained in:
Generated
+11
@@ -142,6 +142,7 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "^4.0.0",
|
||||
"date-fns": "^2.17.0",
|
||||
"deep-object-diff": "^1.1.9",
|
||||
"depd": "^2.0.0",
|
||||
"dexie": "^4.0.7",
|
||||
"dompurify": "^3.0.6",
|
||||
@@ -14652,6 +14653,11 @@
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
|
||||
},
|
||||
"node_modules/deep-object-diff": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz",
|
||||
"integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA=="
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
@@ -55393,6 +55399,11 @@
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
|
||||
},
|
||||
"deep-object-diff": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz",
|
||||
"integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA=="
|
||||
},
|
||||
"deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
|
||||
+2
-1
@@ -161,6 +161,7 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "^4.0.0",
|
||||
"date-fns": "^2.17.0",
|
||||
"deep-object-diff": "^1.1.9",
|
||||
"depd": "^2.0.0",
|
||||
"dexie": "^4.0.7",
|
||||
"dompurify": "^3.0.6",
|
||||
@@ -330,4 +331,4 @@
|
||||
"url": "git+https://Kayaya@bitbucket.org/equilibriumito/gabinete-digital.git"
|
||||
},
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { object, z } from 'zod';
|
||||
import { MessageEntitySchema } from './message';
|
||||
import { BaseEntity } from 'src/app/utils/entity';
|
||||
|
||||
const DistributionEntitySchema = z.object({
|
||||
$messageIdMemberId: z.string().optional(),
|
||||
messageId: z.string(),
|
||||
memberId: z.number(),
|
||||
readAt: z.string().nullable(),
|
||||
deliverAt: z.string().nullable(),
|
||||
roomId: z.string(),
|
||||
})
|
||||
|
||||
export type IDistribution = z.infer<typeof DistributionEntitySchema>
|
||||
|
||||
|
||||
export class DistributionEntity extends BaseEntity<DistributionEntity>(DistributionEntitySchema) implements IDistribution{
|
||||
|
||||
roomId: typeof DistributionEntitySchema._input.roomId
|
||||
readAt: typeof DistributionEntitySchema._input.readAt
|
||||
messageId: typeof DistributionEntitySchema._input.messageId
|
||||
memberId: typeof DistributionEntitySchema._input.memberId
|
||||
deliverAt: typeof DistributionEntitySchema._input.deliverAt
|
||||
|
||||
constructor(data: IDistribution) {
|
||||
super();
|
||||
Object.assign(this, data)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { SessionStore } from "src/app/store/session.service";
|
||||
import { BaseEntity } from "src/app/utils/entity";
|
||||
import { z } from "zod"
|
||||
|
||||
export enum RoomType {
|
||||
@@ -37,7 +38,7 @@ export const RoomEntitySchema = z.object({
|
||||
|
||||
export type IRoomEntity = z.infer<typeof RoomEntitySchema>
|
||||
|
||||
export class RoomEntity implements IRoomEntity{
|
||||
export class RoomEntity extends BaseEntity<RoomEntity>(RoomEntitySchema) implements IRoomEntity{
|
||||
|
||||
id: typeof RoomEntitySchema._input.id
|
||||
roomName: typeof RoomEntitySchema._input.roomName
|
||||
@@ -48,6 +49,7 @@ export class RoomEntity implements IRoomEntity{
|
||||
members: typeof RoomEntitySchema._input.members
|
||||
|
||||
constructor(data: IRoomEntity) {
|
||||
super();
|
||||
Object.assign(this, data)
|
||||
if(data.roomType == RoomType.Direct) {
|
||||
this.setName()
|
||||
|
||||
@@ -14,7 +14,7 @@ export class GetRoomListMapper{
|
||||
id: roomData.chatRoom.id,
|
||||
roomName: roomData.chatRoom.roomName,
|
||||
roomType: roomData.chatRoom.roomType,
|
||||
members: [roomData.chatRoom.user1, roomData.chatRoom.user2].filter((e) => e?.wxUserId).map((b) => ({
|
||||
members: [ roomData.chatRoom.user2, roomData.chatRoom.user1].filter((e) => e?.wxUserId).map((b) => ({
|
||||
id: '',
|
||||
isAdmin: false,
|
||||
joinAt: '',
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { BoldTable } from "src/app/infra/database/dexie/instance/chat/schema/bold";
|
||||
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
|
||||
|
||||
|
||||
export abstract class IBoldLocalRepository extends DexieRepository<BoldTable, BoldTable> implements IBoldLocalRepository {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { DistributionTable, DistributionTableSchema } from "src/app/infra/database/dexie/instance/chat/schema/destribution";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/service";
|
||||
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
|
||||
|
||||
|
||||
|
||||
export abstract class IDistributionLocalRepository extends DexieRepository<DistributionTable, DistributionTable> implements IDistributionLocalRepository {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { EntityTable } from 'Dexie';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const BoldTableSchema = z.object({
|
||||
roomId: z.string(),
|
||||
bold: z.number()
|
||||
})
|
||||
|
||||
export type BoldTable = z.infer<typeof BoldTableSchema>
|
||||
export type DexieBoldTable = EntityTable<BoldTable, 'roomId'>;
|
||||
export const BoldTableColumn = 'roomId, bold'
|
||||
@@ -2,12 +2,14 @@ import { EntityTable } from 'Dexie';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const DistributionTableSchema = z.object({
|
||||
$id: z.string(),
|
||||
$messageIdMemberId: z.string().optional(),
|
||||
messageId: z.string(),
|
||||
memberId: z.number(),
|
||||
readAt: z.string().nullable(),
|
||||
deliverAt: z.string().nullable()
|
||||
deliverAt: z.string().nullable(),
|
||||
roomId: z.string(),
|
||||
})
|
||||
|
||||
export type DistributionTable = z.infer<typeof DistributionTableSchema>
|
||||
export type DexieDistributionTable = EntityTable<DistributionTable, '$id'>;
|
||||
export const DistributionTableColumn = '++$id, messageId, memberId, readAt, deliverAt'
|
||||
export type DexieDistributionTable = EntityTable<DistributionTable, '$messageIdMemberId'>;
|
||||
export const DistributionTableColumn = '$messageIdMemberId, messageId, memberId, readAt, deliverAt, roomId'
|
||||
@@ -6,6 +6,8 @@ import { DexieRoomsTable, RoomTableColumn } from 'src/app/infra/database/dexie/i
|
||||
import { DexieTypingsTable, TypingTableColumn } from 'src/app/infra/database/dexie/instance/chat/schema/typing';
|
||||
import { MessageEntity } from 'src/app/core/chat/entity/message';
|
||||
import { AttachmentTableColumn, DexieAttachmentsTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/attachment';
|
||||
import { DexieDistributionTable, DistributionTable, DistributionTableColumn } from './instance/chat/schema/destribution';
|
||||
import { BoldTableColumn, DexieBoldTable } from './instance/chat/schema/bold';
|
||||
// import FDBFactory from 'fake-indexeddb/lib/FDBFactory';
|
||||
// import FDBKeyRange from 'fake-indexeddb/lib/FDBKeyRange';
|
||||
|
||||
@@ -20,6 +22,8 @@ export const chatDatabase = new Dexie('chat-database-infra',{
|
||||
room: DexieRoomsTable,
|
||||
typing: DexieTypingsTable,
|
||||
attachment: DexieAttachmentsTableSchema,
|
||||
distribution: DexieDistributionTable,
|
||||
bold: DexieBoldTable
|
||||
};
|
||||
|
||||
chatDatabase.version(1).stores({
|
||||
@@ -27,7 +31,9 @@ chatDatabase.version(1).stores({
|
||||
members: MemberTableColumn,
|
||||
room: RoomTableColumn,
|
||||
typing: TypingTableColumn,
|
||||
attachment: AttachmentTableColumn
|
||||
attachment: AttachmentTableColumn,
|
||||
distribution: DistributionTableColumn,
|
||||
bold:BoldTableColumn
|
||||
});
|
||||
|
||||
chatDatabase.message.mapToClass(MessageEntity)
|
||||
|
||||
@@ -77,6 +77,28 @@ export class DexieRepository<T, R> implements IDexieRepository<T, R> {
|
||||
}
|
||||
}
|
||||
|
||||
async updateMany(updatedDocument: Partial<T>[]) {
|
||||
|
||||
const schema = this.ZodSchema.array()
|
||||
const dataValidation = schema.safeParse(updatedDocument)
|
||||
|
||||
if(dataValidation.success) {
|
||||
try {
|
||||
const updatedCount = await this.table.bulkPut(dataValidation.data);
|
||||
return ok(updatedCount);
|
||||
} catch (error) {
|
||||
return err(new Error('Failed to update document: ' + error.message));
|
||||
}
|
||||
} else {
|
||||
Logger.error(`dexie.js failed to update many into ${this.table.name}, invalid data`, {
|
||||
data: document,
|
||||
zodError: dataValidation.error.issues
|
||||
});
|
||||
return err((dataValidation as unknown as ZodError<T>))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async delete(id: any): Promise<RepositoryResult<void, T>> {
|
||||
try {
|
||||
await this.table.delete(id);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { RoomService } from 'src/app/module/chat/domain/service/room.service'
|
||||
import { HttpListenToMessageLoadHistoryAdapter } from './domain/adapter';
|
||||
import { ISignalRService } from 'src/app/infra/socket/adapter';
|
||||
import { HttpModule } from 'src/app/infra/http/http.module';
|
||||
import { HttpListenToMessageLoadHistoryUseCase } from 'src/app/core/chat/usecase/message/http-listen-to-message-load-history-use-case';
|
||||
import { HttpListenToMessageLoadHistoryUseCase } from 'src/app/core/chat/usecase/message/http-listen-to-message-load-history-by-roomId-use-case';
|
||||
import { IMessageLocalRepository } from 'src/app/core/chat/repository/message/message-local-repository';
|
||||
import { MessageLocalDataSourceService } from './data/repository/message/message-local-data-source.service';
|
||||
import { MessageRemoteDataSourceService } from './data/repository/message/message-remote-data-source.service';
|
||||
@@ -31,6 +31,12 @@ import { IAttachmentLocalRepository } from 'src/app/core/chat/repository/typing/
|
||||
import { AttachmentLocalDataSource } from './data/repository/attachment/attachment-local-repository.service';
|
||||
import { IAttachmentRemoteRepository } from 'src/app/core/chat/repository/attachment/attachment-remote-repository';
|
||||
import { AttachmentRemoteDataSourceService } from './data/repository/attachment/attachment-remote-repository.service';
|
||||
import { IDistributionLocalRepository } from 'src/app/core/chat/repository/distribution/distribution-local-repository';
|
||||
import { DistributionLocalRepository } from './data/repository/destribution/destribution-local-repository';
|
||||
import { DistributionService } from './domain/service/distribution.service'
|
||||
import { BoldLocalRepository } from './data/repository/bold/bold-local-repository';
|
||||
import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository';
|
||||
import { BoldService } from 'src/app/module/chat/domain/service/bold.service'
|
||||
@NgModule({
|
||||
imports: [HttpModule],
|
||||
providers: [
|
||||
@@ -86,6 +92,15 @@ import { AttachmentRemoteDataSourceService } from './data/repository/attachment/
|
||||
provide: IAttachmentRemoteRepository,
|
||||
useClass: AttachmentRemoteDataSourceService
|
||||
},
|
||||
//
|
||||
{
|
||||
provide: IDistributionLocalRepository,
|
||||
useClass: DistributionLocalRepository
|
||||
},
|
||||
{
|
||||
provide: IBoldLocalRepository,
|
||||
useClass: BoldLocalRepository
|
||||
}
|
||||
],
|
||||
declarations: [],
|
||||
schemas: [],
|
||||
@@ -101,7 +116,9 @@ export class ChatModule {
|
||||
private signalR: SignalRService,
|
||||
private localDataSource: UserTypingLocalRepository,
|
||||
private UserTypingRemoteRepositoryService: UserTypingRemoteRepositoryService,
|
||||
private RoomService: RoomService
|
||||
private RoomService: RoomService,
|
||||
private DistributionService: DistributionService,
|
||||
private BoldService: BoldService
|
||||
) {
|
||||
|
||||
this.RoomService.init()
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
import { DistributionTable } from "src/app/infra/database/dexie/instance/chat/schema/destribution";
|
||||
import { DistributionOutPutDTO } from "src/app/module/chat/domain/service/distribution.service";
|
||||
|
||||
export function distributionListDetermineChanges(____serverDistributions: DistributionOutPutDTO[], localDistributions: DistributionTable[], messageId: string) {
|
||||
|
||||
const serverDistribution = ____serverDistributions.map( e=> {
|
||||
return {
|
||||
...e,
|
||||
$messageIdMemberId: messageId + e.memberId
|
||||
}
|
||||
})
|
||||
|
||||
const serverDistributionMap = new Map(serverDistribution.map(distribution => [distribution.$messageIdMemberId, distribution]));
|
||||
const localDistributionMap = new Map(localDistributions.map(distribution => [distribution.$messageIdMemberId, distribution]));
|
||||
|
||||
const distributionToInsert = serverDistribution.filter(distribution => !localDistributionMap.has(distribution.$messageIdMemberId));
|
||||
const distributionToUpdate = serverDistribution.filter(distribution => {
|
||||
const localDistribution = localDistributionMap.get(distribution.$messageIdMemberId);
|
||||
return localDistribution && (
|
||||
distribution.deliverAt !== localDistribution.deliverAt ||
|
||||
distribution.readAt !== localDistribution.readAt
|
||||
)
|
||||
});
|
||||
|
||||
const distributionToDelete = localDistributions.filter(distribution => !serverDistributionMap.has(distribution.$messageIdMemberId));
|
||||
|
||||
return { distributionToInsert, distributionToUpdate, distributionToDelete };
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { RoomTable } from "src/app/infra/database/dexie/instance/chat/schema/room";
|
||||
import { RoomByIdOutputDTO } from "src/app/module/chat/domain/use-case/room/room-get-by-id-use-case.service";
|
||||
import { RoomListItemOutPutDTO } from "src/app/module/chat/domain/use-case/room/room-get-list-use-case.service";
|
||||
|
||||
export function roomByIdDetermineChanges(serverResponse: RoomByIdOutputDTO, localRooms: RoomTable[]) {
|
||||
|
||||
const localRoomMap = new Map(localRooms.map(room => [room.id, room]));
|
||||
|
||||
let roomsToInsert:RoomByIdOutputDTO | undefined;
|
||||
let roomsToUpdate: RoomByIdOutputDTO | undefined;
|
||||
|
||||
const fond = localRooms.filter(room => !localRoomMap.has(serverResponse.data.id));
|
||||
if(!fond) {
|
||||
roomsToInsert = serverResponse
|
||||
}
|
||||
|
||||
const needToUpdate = localRooms.filter(room => {
|
||||
const localRoom = localRoomMap.get(room.id);
|
||||
return localRoom && (
|
||||
room.roomName !== serverResponse.data.roomName ||
|
||||
room.createdBy.wxUserId !== serverResponse.data.createdBy.wxUserId ||
|
||||
room.createdAt !== serverResponse.data.createdAt ||
|
||||
room.expirationDate !== serverResponse.data.expirationDate // ||
|
||||
// room.chatRoom.roomType !== localRoom.roomType
|
||||
);
|
||||
});
|
||||
|
||||
if(needToUpdate) {
|
||||
roomsToUpdate = serverResponse
|
||||
}
|
||||
|
||||
return { roomsToInsert, roomsToUpdate };
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { RoomType } from "src/app/core/chat/entity/group";
|
||||
import { RoomTable } from "src/app/infra/database/dexie/instance/chat/schema/room";
|
||||
import { RoomListItemOutPutDTO } from "src/app/module/chat/domain/use-case/room/room-get-list-use-case.service";
|
||||
|
||||
@@ -8,8 +9,9 @@ export function roomListDetermineChanges(serverRooms: RoomListItemOutPutDTO[], l
|
||||
const roomsToInsert = serverRooms.filter(room => !localRoomMap.has(room.chatRoom.id));
|
||||
const roomsToUpdate = serverRooms.filter(room => {
|
||||
const localRoom = localRoomMap.get(room.chatRoom.id);
|
||||
|
||||
return localRoom && (
|
||||
room.chatRoom.roomName !== localRoom.roomName ||
|
||||
room.chatRoom.roomName !== localRoom.roomName && room.chatRoom.roomType == RoomType.Group ||
|
||||
room.chatRoom.createdBy.wxUserId !== localRoom.createdBy.wxUserId ||
|
||||
room.chatRoom.createdAt !== localRoom.createdAt ||
|
||||
room.chatRoom.expirationDate !== localRoom.expirationDate // ||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { from } from "rxjs";
|
||||
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
|
||||
import { Dexie, EntityTable, liveQuery, Observable } from 'Dexie';
|
||||
import { BoldTable, BoldTableSchema } from "src/app/infra/database/dexie/instance/chat/schema/bold";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/service";
|
||||
import { IBoldLocalRepository } from "src/app/core/chat/repository/bold/bold-local-repository";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class BoldLocalRepository extends DexieRepository<BoldTable, BoldTable> implements IBoldLocalRepository {
|
||||
constructor() {
|
||||
super(chatDatabase.bold, BoldTableSchema)
|
||||
}
|
||||
|
||||
listen() {
|
||||
return from(liveQuery(() => chatDatabase.bold.toArray()))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { DistributionTable, DistributionTableSchema } from "src/app/infra/database/dexie/instance/chat/schema/destribution";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/service";
|
||||
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
|
||||
|
||||
|
||||
export class DistributionLocalRepository extends DexieRepository<DistributionTable, DistributionTable> {
|
||||
constructor() {
|
||||
super(chatDatabase.distribution, DistributionTableSchema)
|
||||
|
||||
chatDatabase.distribution.hook("creating", function (primKey, obj, transaction) {
|
||||
obj.$messageIdMemberId = `${obj.messageId}${obj.memberId}`
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { HttpErrorResponse } from "@angular/common/http";
|
||||
import { Result } from "neverthrow";
|
||||
import { Observable } from "rxjs";
|
||||
import { MessageEntity } from "src/app/core/chat/entity/message";
|
||||
import { HttpListenToMessageLoadHistoryUseCaseInput } from "src/app/core/chat/usecase/message/http-listen-to-message-load-history-use-case";
|
||||
import { HttpListenToMessageLoadHistoryUseCaseInput } from "src/app/core/chat/usecase/message/http-listen-to-message-load-history-by-roomId-use-case";
|
||||
import { HttpResult } from "src/app/infra/http/type";
|
||||
import { UseCase } from "src/app/utils/use-case-interface";
|
||||
import { IMessageGetAllByRoomIdOutPut } from 'src/app/core/chat/usecase/message/message-get-all-by-room-Id'
|
||||
|
||||
@@ -36,10 +36,10 @@ import { MessageAttachmentByMessageIdInput, MessageAttachmentByMessageIdUseCase
|
||||
import { AddMemberToRoomInputDTO, AddMemberToRoomInputDTOSchema } from '../domain/use-case/member/member-add-use-case.service';
|
||||
import { RoomType } from "src/app/core/chat/entity/group";
|
||||
import { HttpListenToMessageLoadHistoryAdapter } from './adapter'
|
||||
import { HttpListenToMessageLoadHistoryUseCaseInput } from 'src/app/core/chat/usecase/message/http-listen-to-message-load-history-use-case';
|
||||
import { HttpListenToMessageLoadHistoryUseCaseInput } from 'src/app/core/chat/usecase/message/http-listen-to-message-load-history-by-roomId-use-case';
|
||||
import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service'
|
||||
import { MessageMarkAsReadInput } from "src/app/module/chat/domain/use-case/message/message-mark-as-read-use-case.service";
|
||||
|
||||
import { BoldRemoveByRoomIdInput, BoldRemoveByRoomIdService } from 'src/app/module/chat/domain/use-case/bold/bold-remove-by-room-id.service'
|
||||
export const InstanceId = uuidv4();
|
||||
|
||||
@Injectable({
|
||||
@@ -80,6 +80,7 @@ export class ChatServiceService {
|
||||
private MessageMarkAllMessageAsReadByRoomIdService: MessageMarkAllMessageAsReadByRoomIdService,
|
||||
private HttpListenToMessageLoadHistory: HttpListenToMessageLoadHistoryAdapter,
|
||||
private MessageSocketRepositoryService: MessageSocketRepositoryService,
|
||||
private BoldRemoveByRoomIdService: BoldRemoveByRoomIdService
|
||||
) {
|
||||
this.MessageSocketRepositoryService.listenToDeleteMessages()
|
||||
.pipe()
|
||||
@@ -182,6 +183,9 @@ export class ChatServiceService {
|
||||
// return this.GetMessageAttachmentLocallyUseCaseService.execute(input)
|
||||
// }
|
||||
|
||||
removeBoldFromRoom(input: BoldRemoveByRoomIdInput) {
|
||||
return this.BoldRemoveByRoomIdService.execute(input)
|
||||
}
|
||||
|
||||
listenToMessageLoadHistory(input: HttpListenToMessageLoadHistoryUseCaseInput) {
|
||||
return this.HttpListenToMessageLoadHistory.execute(input)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BoldService } from './bold.service';
|
||||
|
||||
describe('BoldService', () => {
|
||||
let service: BoldService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(BoldService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { IMessageSocketRepository } from 'src/app/core/chat/repository/message/message-socket-repository';
|
||||
import { InstanceId } from '../chat-service.service';
|
||||
import { MessageEntity } from 'src/app/core/chat/entity/message';
|
||||
import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class BoldService {
|
||||
|
||||
constructor(
|
||||
private MessageSocketRepositoryService: IMessageSocketRepository,
|
||||
private boldLocalRepository: IBoldLocalRepository
|
||||
) {
|
||||
this.listenToIncomingMessage();
|
||||
}
|
||||
|
||||
listenToIncomingMessage() {
|
||||
return this.MessageSocketRepositoryService.listenToMessages().pipe(
|
||||
filter((message) => !message?.requestId?.startsWith(InstanceId)),
|
||||
map(message => Object.assign(new MessageEntity(), message))
|
||||
).subscribe(async (message) => {
|
||||
|
||||
const result = await this.boldLocalRepository.findOne({roomId: message.roomId})
|
||||
|
||||
if(result.isOk() && !result.value) {
|
||||
const result = await this.boldLocalRepository.insert({roomId: message.roomId, bold: 1})
|
||||
} else if(result.isOk() && result.value.bold == 0) {
|
||||
const result = await this.boldLocalRepository.update(message.roomId, {bold: 1})
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DistributionService } from './distribution.service';
|
||||
|
||||
describe('DistributionService', () => {
|
||||
let service: DistributionService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(DistributionService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { IMessageGetAllByRoomIdOutPut } from 'src/app/core/chat/usecase/message/message-get-all-by-room-Id';
|
||||
import { HttpAdapter } from 'src/app/infra/http/adapter';
|
||||
import { IDistributionLocalRepository } from 'src/app/core/chat/repository/distribution/distribution-local-repository'
|
||||
import { z } from 'zod';
|
||||
import { distributionListDetermineChanges } from '../../data/async/list/rooms/distributionListChangedetector';
|
||||
import { DistributionEntity } from 'src/app/core/chat/entity/distribution';
|
||||
|
||||
export const DistributionOutPutDTOSchema = z.object({
|
||||
$messageIdMemberId: z.string(),
|
||||
memberId: z.number(),
|
||||
readAt: z.string().nullable(),
|
||||
deliverAt: z.string().nullable()
|
||||
})
|
||||
export type DistributionOutPutDTO = z.infer<typeof DistributionOutPutDTOSchema>
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DistributionService {
|
||||
|
||||
constructor(
|
||||
private http: HttpAdapter,
|
||||
private distributionLocalRepository: IDistributionLocalRepository
|
||||
) {
|
||||
// this.listenToLoadHistory()
|
||||
}
|
||||
|
||||
listenToLoadHistory() {
|
||||
return this.http.listen().pipe(
|
||||
filter((response)=> {
|
||||
if(response?.isOk()) {
|
||||
return response.value.url.endsWith('Messages')
|
||||
}
|
||||
|
||||
return false
|
||||
}),
|
||||
map((response: any) => response.value.data as IMessageGetAllByRoomIdOutPut)
|
||||
)
|
||||
.subscribe(async (data) => {
|
||||
|
||||
const localList = await this.distributionLocalRepository.find({roomId: data.data[0].roomId})
|
||||
|
||||
data.data.map(async (message) => {
|
||||
const serverList = message.info
|
||||
|
||||
if(localList.isOk() && localList.value) {
|
||||
|
||||
// const localListForCurrentMessage = localList.value.filter((e) => e.messageId == message.id)
|
||||
|
||||
// console.log('localListForCurrentMessage', localListForCurrentMessage)
|
||||
|
||||
// const { distributionToInsert, distributionToUpdate, distributionToDelete } = await distributionListDetermineChanges(serverList, localListForCurrentMessage, message.id)
|
||||
// console.log({distributionToInsert, distributionToUpdate, distributionToDelete})
|
||||
|
||||
// const map = distributionToInsert.map((e) => {
|
||||
// e.
|
||||
// })
|
||||
|
||||
// this.distributionLocalRepository.insertMany(distributionToInsert)
|
||||
|
||||
// const distributionEntityToInsert = distributionToInsert.map((ee)=> {
|
||||
// return new DistributionEntity({
|
||||
// roomId: message.roomId,
|
||||
// deliverAt: ee.deliverAt,
|
||||
// memberId: ee.memberId,
|
||||
// messageId: message.roomId,
|
||||
// readAt: ee.readAt,
|
||||
// })
|
||||
|
||||
// console.log('create')
|
||||
// })
|
||||
|
||||
// if(distributionEntityToInsert.length >= 0) {
|
||||
// // console.log('distributionEntityToInsert', distributionEntityToInsert)
|
||||
// //this.distributionLocalRepository.insertMany(distributionEntityToInsert)
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BoldRemoveByRoomIdService } from './bold-remove-by-room-id.service';
|
||||
|
||||
describe('BoldRemoveByRoomIdService', () => {
|
||||
let service: BoldRemoveByRoomIdService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(BoldRemoveByRoomIdService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository';
|
||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
||||
const BoldRemoveByRoomIdInputSchema = z.object({
|
||||
roomId: z.string()
|
||||
})
|
||||
export type BoldRemoveByRoomIdInput = z.infer<typeof BoldRemoveByRoomIdInputSchema>
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class BoldRemoveByRoomIdService {
|
||||
|
||||
constructor(
|
||||
private boldLocalRepository: IBoldLocalRepository
|
||||
) { }
|
||||
|
||||
@XTracerAsync({name:'BoldRemoveByRoomIdService', module:'chat', bugPrint: true})
|
||||
async execute(input: BoldRemoveByRoomIdInput, tracing?: TracingType) {
|
||||
|
||||
const validation = zodSafeValidation<any>(BoldRemoveByRoomIdInputSchema, input)
|
||||
|
||||
if(validation.isOk()) {
|
||||
return await this.boldLocalRepository.delete(input.roomId)
|
||||
} else {
|
||||
tracing.hasError("invalid parameter")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,11 @@ import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-re
|
||||
import { IMemberLocalRepository } from 'src/app/core/chat/repository/member/member-local-repository';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { GetRoomByIdMapper } from 'src/app/core/chat/mapper/getRoomByIdMapper';
|
||||
import { RoomEntity } from 'src/app/core/chat/entity/group';
|
||||
import { RoomEntity, RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { GetRoomListMapper } from 'src/app/core/chat/mapper/getRoomListMapper';
|
||||
import { roomByIdDetermineChanges } from '../../../data/async/list/rooms/roomByIdChangeDetector';
|
||||
import { diff, addedDiff, deletedDiff, updatedDiff, detailedDiff } from 'deep-object-diff';
|
||||
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||
|
||||
const UserSchema = z.object({
|
||||
wxUserId: z.number(),
|
||||
@@ -56,7 +59,6 @@ export class GetRoomByIdUseCaseService {
|
||||
|
||||
constructor(
|
||||
private roomRemoteDataSourceService: IRoomRemoteRepository,
|
||||
// private roomMemoryDataSourceService: Store<RoomRemoteDataSourceState>,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
private MemberListLocalRepository: IMemberLocalRepository
|
||||
) { }
|
||||
@@ -64,71 +66,63 @@ export class GetRoomByIdUseCaseService {
|
||||
@captureAndReraiseAsync('RoomRepositoryService/getRoomById')
|
||||
async execute(id: RoomByIdInputDTO) {
|
||||
const result = await this.roomRemoteDataSourceService.getRoom(id)
|
||||
|
||||
|
||||
if(result.isOk()) {
|
||||
const validData = zodSafeValidation<RoomByIdOutputDTO>(RoomByIdOutputDTOSchema, result.value)
|
||||
|
||||
const localListRoom = await this.roomLocalDataSourceService.findAll()
|
||||
if(localListRoom.isOk()) {
|
||||
const object = {
|
||||
chatRoom: result.value.data
|
||||
}
|
||||
const { roomsToInsert, roomsToUpdate } = roomListDetermineChanges([object], localListRoom.value)
|
||||
|
||||
if(roomsToUpdate) {
|
||||
|
||||
const roomsToUpdateEntity = GetRoomListMapper.toDomain(roomsToUpdate)
|
||||
for( const room of roomsToUpdateEntity) {
|
||||
this.roomLocalDataSourceService.update(room.id, room)
|
||||
if(room.expirationDate) {
|
||||
console.log('room expiration date schedule')
|
||||
// this.CronJobService.createCronJob('remove expired room', new Date(room.expirationDate), this.execute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(roomsToInsert) {
|
||||
|
||||
const roomsToInsertEntity = GetRoomListMapper.toDomain(roomsToInsert)
|
||||
for( const room of roomsToInsertEntity) {
|
||||
this.roomLocalDataSourceService.insert(room)
|
||||
if(room.expirationDate) {
|
||||
console.log('room expiration date schedule')
|
||||
// this.CronJobService.createCronJob('remove expired room', new Date(room.expirationDate), this.execute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for( const roomData of roomsToUpdate) {
|
||||
// const room = new RoomEntity({
|
||||
// createdAt: result.value.data.createdAt,
|
||||
// createdBy: result.value.data.createdBy,
|
||||
// expirationDate: result.value.data.expirationDate,
|
||||
// id: result.value.data.id,
|
||||
// members: result.value.data.members,
|
||||
// roomName: result.value.data.roomName,
|
||||
// roomType: result.value.data.roomType,
|
||||
// })
|
||||
if(validData.isOk()) {
|
||||
const localListRoom = await this.roomLocalDataSourceService.findAll()
|
||||
if(localListRoom.isOk()) {
|
||||
|
||||
// this.roomLocalDataSourceService.update(room.id, room)
|
||||
// }
|
||||
|
||||
// ============================
|
||||
const localList = await this.MemberListLocalRepository.getRoomMemberById(id)
|
||||
|
||||
const { membersToInsert, membersToUpdate, membersToDelete } = roomMemberListDetermineChanges(result.value.data.members, localList, id)
|
||||
|
||||
for (const user of membersToInsert) {
|
||||
await this.MemberListLocalRepository.addMember(MemberListMapper(user, id))
|
||||
const getRoomById = await this.roomLocalDataSourceService.findOne({id:validData.value.data.id})
|
||||
if(getRoomById.isOk() && getRoomById.value) {
|
||||
console.log(validData.value)
|
||||
const room = GetRoomByIdMapper.toDomain(validData.value)
|
||||
|
||||
const added: Partial<RoomEntity> = addedDiff(getRoomById.value, room);
|
||||
const deleted: Partial<RoomEntity> = deletedDiff(getRoomById.value, room);
|
||||
const updated: Partial<RoomEntity> = updatedDiff(getRoomById.value, room);
|
||||
|
||||
delete added.members
|
||||
if(room.roomType == RoomType.Direct) {
|
||||
delete updated.roomName
|
||||
}
|
||||
|
||||
if(Object.keys(added).length >= 1 || Object.keys(updated).length >= 1) {
|
||||
console.log('added', added);
|
||||
console.log('deleted', deleted);
|
||||
console.log('updated', updated);
|
||||
this.roomLocalDataSourceService.update(room.id, room)
|
||||
}
|
||||
|
||||
} else if (getRoomById.isOk() && !getRoomById.value) {
|
||||
console.log(validData.value)
|
||||
const room = GetRoomByIdMapper.toDomain(validData.value)
|
||||
this.roomLocalDataSourceService.insert(room)
|
||||
}
|
||||
|
||||
|
||||
// ============================
|
||||
const localList = await this.MemberListLocalRepository.getRoomMemberById(id)
|
||||
|
||||
const { membersToInsert, membersToUpdate, membersToDelete } = roomMemberListDetermineChanges(validData.value.data.members, localList, id)
|
||||
|
||||
for (const user of membersToInsert) {
|
||||
await this.MemberListLocalRepository.addMember(MemberListMapper(user, id))
|
||||
}
|
||||
|
||||
for (const user of membersToUpdate) {
|
||||
await this.MemberListLocalRepository.updateMemberRole(MemberListMapper(user, id))
|
||||
}
|
||||
|
||||
for(const user of membersToDelete) {
|
||||
await this.MemberListLocalRepository.removeMemberFromRoom(user.$roomIdUserId)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for (const user of membersToUpdate) {
|
||||
await this.MemberListLocalRepository.updateMemberRole(MemberListMapper(user, id))
|
||||
}
|
||||
|
||||
for(const user of membersToDelete) {
|
||||
await this.MemberListLocalRepository.removeMemberFromRoom(user.$roomIdUserId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else if (isHttpResponse(result.error) ) {
|
||||
@@ -140,4 +134,4 @@ export class GetRoomByIdUseCaseService {
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,9 +80,7 @@ export class GetRoomListUseCaseService {
|
||||
}
|
||||
|
||||
const roomsToUpdateEntity = GetRoomListMapper.toDomain(roomsToUpdate)
|
||||
for( const room of roomsToUpdateEntity) {
|
||||
this.roomLocalDataSourceService.update(room.id, room)
|
||||
}
|
||||
this.roomLocalDataSourceService.updateMany(roomsToUpdateEntity)
|
||||
|
||||
for( const room of roomsToDelete) {
|
||||
this.roomLocalDataSourceService.delete(room.id)
|
||||
|
||||
@@ -21,6 +21,8 @@ import { MessagesPageModule } from './component/messages/messages.module';
|
||||
import { ContactsPageModule } from './component/contacts/contacts.module';
|
||||
import { NewGroupPageModule } from './component/new-group/new-group.module';
|
||||
import { ChatModule } from 'src/app/module/chat/chat.module';
|
||||
import { IBoldLocalRepository } from 'src/app/core/chat/repository/bold/bold-local-repository';
|
||||
import { BoldLocalRepository } from 'src/app/module/chat/data/repository/bold/bold-local-repository';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -42,6 +44,9 @@ import { ChatModule } from 'src/app/module/chat/chat.module';
|
||||
ImageCropperModule,
|
||||
AttendeeModalPageModule,
|
||||
ChatModule
|
||||
],
|
||||
providers: [
|
||||
|
||||
],
|
||||
declarations: [
|
||||
ChatPage
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<ion-label >
|
||||
<span >
|
||||
<div >
|
||||
<div class="font-15-em" [class.bold-message]="true">
|
||||
<div class="font-15-em" [class.bold-message]="boldTable?.[room.id]?.bold">
|
||||
{{room.roomName}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,7 +99,7 @@
|
||||
<ion-label >
|
||||
<span >
|
||||
<div >
|
||||
<div class="font-15-em" [class.bold-message]="true">
|
||||
<div class="font-15-em" [class.bold-message]="boldTable?.[room.id]?.bold">
|
||||
{{room.roomName}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,8 @@ import { map, tap } from 'rxjs/operators';
|
||||
import { interval, Subscription } from 'rxjs';
|
||||
import { RoomTable } from 'src/app/infra/database/dexie/instance/chat/schema/room';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
|
||||
import { BoldLocalRepository } from 'src/app/module/chat/data/repository/bold/bold-local-repository'
|
||||
import { BoldTable } from 'src/app/infra/database/dexie/instance/chat/schema/bold';
|
||||
@Component({
|
||||
selector: 'app-chat',
|
||||
templateUrl: './chat.page.html',
|
||||
@@ -64,6 +65,8 @@ export class ChatPage implements OnInit {
|
||||
|
||||
RoomType = RoomType
|
||||
|
||||
boldTable: {[key: string]: BoldTable} = {}
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
private timeService: TimeService,
|
||||
@@ -73,18 +76,27 @@ export class ChatPage implements OnInit {
|
||||
public RouteService: RouteService,
|
||||
private ChatServiceService: ChatServiceService,
|
||||
private roomLocalDataSourceService: RoomLocalRepository,
|
||||
private chatServiceService: ChatServiceService
|
||||
private boldLocalRepository: BoldLocalRepository
|
||||
) {
|
||||
|
||||
|
||||
window.onresize = (event) => {
|
||||
if (window.innerWidth > 701) {
|
||||
this.modalController.dismiss();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.showLoader = true;
|
||||
|
||||
this.boldLocalRepository.listen().subscribe((data) => {
|
||||
const distributionObject: {[key: string]: BoldTable} = {};
|
||||
|
||||
for (const distribution of data) {
|
||||
distributionObject[distribution.roomId] = distribution;
|
||||
}
|
||||
|
||||
this.boldTable = distributionObject
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// Fetch all items using useLiveQuery
|
||||
@@ -127,7 +139,7 @@ export class ChatPage implements OnInit {
|
||||
this.routerSubscription = this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd && event.url.startsWith('/home/chat')) {
|
||||
this.routeCheck()
|
||||
this.ChatServiceService.getRoomList()
|
||||
// this.ChatServiceService.getRoomList()
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
}) as any
|
||||
|
||||
|
||||
|
||||
this.chatServiceService.removeBoldFromRoom({roomId: this.roomId})
|
||||
}
|
||||
|
||||
messageStatus(message: MessageEntity) {
|
||||
@@ -422,7 +422,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
setTimeout(() => {
|
||||
this.scrollToBottomClicked()
|
||||
}, 100)
|
||||
|
||||
this.chatServiceService.removeBoldFromRoom({roomId: this.roomId})
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
listenToDeleteMessage() {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { ZodSchema, ZodType } from 'zod';
|
||||
|
||||
|
||||
|
||||
// export interface IEntity {
|
||||
// id: string;
|
||||
|
||||
// createdAt: Date;
|
||||
|
||||
// updatedAt: Date;
|
||||
|
||||
// deletedAt?: Date;
|
||||
// }
|
||||
|
||||
export const BaseEntity = <T>(schema: ZodSchema) => {
|
||||
abstract class Entity {
|
||||
readonly id: string;
|
||||
|
||||
readonly createdAt: Date;
|
||||
|
||||
readonly updatedAt: Date;
|
||||
|
||||
deletedAt?: Date;
|
||||
|
||||
static nameOf = (name: keyof T) => name;
|
||||
|
||||
validate<T>(entity: T): ZodType {
|
||||
return schema.parse(entity);
|
||||
}
|
||||
}
|
||||
|
||||
return Entity;
|
||||
};
|
||||
Reference in New Issue
Block a user