diff --git a/src/app/modals/set-room-owner/set-room-owner.page.ts b/src/app/modals/set-room-owner/set-room-owner.page.ts index baa033d09..acb9316aa 100644 --- a/src/app/modals/set-room-owner/set-room-owner.page.ts +++ b/src/app/modals/set-room-owner/set-room-owner.page.ts @@ -1,12 +1,12 @@ import { Component, OnInit } from '@angular/core'; import { ModalController, NavParams } from '@ionic/angular'; -import { TableMemberList } from 'src/app/module/chat/data/data-source/room/rooom-local-data-source.service'; import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service'; import { ThemeService } from 'src/app/services/theme.service' import { ToastService } from 'src/app/services/toast.service'; import { Observable as DexieObservable } from 'Dexie'; import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'; +import { MemberTable } from 'src/app/module/chat/infra/database/dexie/schema/members'; @Component({ selector: 'app-set-room-owner', @@ -18,7 +18,7 @@ export class SetRoomOwnerPage implements OnInit { textSearch:string = ""; roomId:any; members:any; - roomMembers$: DexieObservable + roomMembers$: DexieObservable constructor( private modalController: ModalController, @@ -45,7 +45,7 @@ export class SetRoomOwnerPage implements OnInit { this.textSearch = event.detail.value; } - separateLetter(record:TableMemberList, recordIndex, records:TableMemberList[]) { + separateLetter(record:MemberTable, recordIndex, records:MemberTable[]) { if(recordIndex == 0){ return record.wxFullName[0]; } @@ -59,7 +59,7 @@ export class SetRoomOwnerPage implements OnInit { return null; } - async setRoomOwner(user:TableMemberList) { + async setRoomOwner(user:MemberTable) { const result = await this.chatServiceService.setAdmin({ roomId: user.roomId, diff --git a/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts b/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts index ca89048fd..7712914f9 100644 --- a/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts +++ b/src/app/module/chat/data/async/list/rooms/messageListChangedetector.ts @@ -1,4 +1,3 @@ -import { TableRoom } from "../../../data-source/room/rooom-local-data-source.service"; import { RoomListItemOutPutDTO, RoomListOutPutDTO } from "../../../dto/room/roomListOutputDTO"; export function messageListDetermineChanges(serverList: any[], localList: any[]) { diff --git a/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts b/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts index fc9ab0b05..12495e6e3 100644 --- a/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts +++ b/src/app/module/chat/data/async/list/rooms/roomListChangeDetector.ts @@ -1,7 +1,7 @@ -import { TableRoom } from "../../../data-source/room/rooom-local-data-source.service"; +import { RoomTable } from "src/app/module/chat/infra/database/dexie/schema/room"; import { RoomListItemOutPutDTO, RoomListOutPutDTO } from "../../../dto/room/roomListOutputDTO"; -export function roomListDetermineChanges(serverRooms: RoomListItemOutPutDTO[], localRooms: TableRoom[]) { +export function roomListDetermineChanges(serverRooms: RoomListItemOutPutDTO[], localRooms: RoomTable[]) { const serverRoomMap = new Map(serverRooms.map(room => [room.chatRoom.id, room])); const localRoomMap = new Map(localRooms.map(room => [room.id, room])); diff --git a/src/app/module/chat/data/async/list/rooms/roomMembersChangeDetector.ts b/src/app/module/chat/data/async/list/rooms/roomMembersChangeDetector.ts index d6088a9b8..601d74895 100644 --- a/src/app/module/chat/data/async/list/rooms/roomMembersChangeDetector.ts +++ b/src/app/module/chat/data/async/list/rooms/roomMembersChangeDetector.ts @@ -1,7 +1,7 @@ -import { TableMemberList } from "../../../data-source/room/rooom-local-data-source.service"; +import { MemberTable } from "src/app/module/chat/infra/database/dexie/schema/members"; import { RoomByIdMemberItemOutputDTO } from "../../../dto/room/roomByIdOutputDTO"; -export function roomMemberListDetermineChanges(____serverRooms: RoomByIdMemberItemOutputDTO[], localRooms: TableMemberList[], roomId: string) { +export function roomMemberListDetermineChanges(____serverRooms: RoomByIdMemberItemOutputDTO[], localRooms: MemberTable[], roomId: string) { const PServerRooms: (RoomByIdMemberItemOutputDTO & {$roomIdUserId: string})[] = ____serverRooms.map( e=> { diff --git a/src/app/module/chat/data/data-source/member-list/member-list-local-data-source.service.ts b/src/app/module/chat/data/data-source/member-list/member-list-local-data-source.service.ts index 9e0e818c3..f99e80074 100644 --- a/src/app/module/chat/data/data-source/member-list/member-list-local-data-source.service.ts +++ b/src/app/module/chat/data/data-source/member-list/member-list-local-data-source.service.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service'; -const TableMemberListSchema = z.object({ +const MemberTableSchema = z.object({ $roomIdUserId: z.string().optional(), id: z.string(), roomId: z.string(), @@ -19,12 +19,12 @@ const TableMemberListSchema = z.object({ status: z.string() }) -export type ITableMemberList = z.infer +export type IMemberTable = z.infer -type ITableMemberListSchema = EntityTable +type IMemberTableSchema = EntityTable // Database declaration (move this to its own module also) export const roomMemberList = new Dexie('roomMemberList') as Dexie & { - memberList: EntityTable; + memberList: EntityTable; }; roomMemberList.version(1).stores({ @@ -34,7 +34,7 @@ roomMemberList.version(1).stores({ @Injectable({ providedIn: 'root' }) -export class MemberListLocalDataSourceService extends DexieRepository { +export class MemberListLocalDataSourceService extends DexieRepository { constructor() { super(roomMemberList.memberList); diff --git a/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts b/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts index 0c0db5bdd..a71f074a6 100644 --- a/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts +++ b/src/app/module/chat/data/data-source/message/message-local-data-source.service.ts @@ -1,91 +1,30 @@ import { Injectable } from '@angular/core'; import { Dexie, EntityTable, liveQuery } from 'Dexie'; import { err, ok, Result } from 'neverthrow'; -import { z } from 'zod'; import { from, Observable, Subject } from 'rxjs'; import { filter } from 'rxjs/operators'; import { MessageInputDTO } from '../../dto/message/messageInputDtO'; import { MessageEntity } from '../../../domain/entity/message'; import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service'; - - -const tableSchema = z.object({ - $id: z.number().optional(), - id: z.string().optional(), - roomId: z.string().uuid(), - message: z.string(), - messageType: z.number(), - canEdit: z.boolean(), - oneShot: z.boolean(), - sentAt: z.string().optional(), - requireUnlock: z.boolean(), - sender: z.object({ - wxUserId: z.number(), - wxFullName: z.string(), - wxeMail: z.string(), - userPhoto: z.string(), - }), - sending: z.boolean().optional(), - reaction: z.object({ - id: z.string(), - reactedAt: z.string(), - reaction: z.string(), - sender: z.object({}), - }).array() -}) - -export const IncomingMessageSchema = z.object({ - messageId: z.string().optional(), - roomId: z.string().uuid(), - message: z.string(), - messageType: z.number(), - canEdit: z.boolean(), - oneShot: z.boolean(), - sentAt: z.string().optional(), - requireUnlock: z.boolean(), - sender: z.object({ - wxUserId: z.number(), - wxFullName: z.string(), - wxeMail: z.string(), - userPhoto: z.string(), - }), - sending: z.boolean().optional() -}) - - -export type TableMessage = z.infer - -// Database declaration (move this to its own module also) -export const messageDataSource = new Dexie('chat-message') as Dexie & { - message: EntityTable; -}; - -messageDataSource.version(1).stores({ - message: '++$id, id, roomId, message, messageType, canEdit, oneShot, requireUnlock, messageId, info' -}); -messageDataSource.message.mapToClass(MessageEntity); +import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message'; +import { chatDatabase } from '../../../infra/database/dexie/service'; @Injectable({ providedIn: 'root' }) -export class MessageLocalDataSourceService extends DexieRepository { +export class MessageLocalDataSourceService extends DexieRepository { messageSubject = new Subject(); constructor() { - super(messageDataSource.message) - // messageDataSource.message.hook('creating', (primKey, obj, trans) => { - // // const newMessage = await trans.table('message').get(primKey); - // this.messageSubject.next(obj); - // // return newMessage - // }) + super(chatDatabase.message) } async setAllSenderToFalse() { try { - await messageDataSource.transaction('rw', messageDataSource.message, async () => { + await chatDatabase.transaction('rw', chatDatabase.message, async () => { // Perform the update operation within the transaction - await messageDataSource.message.toCollection().modify({ sending: false }); + await chatDatabase.message.toCollection().modify({ sending: false }); }); console.log('All messages updated successfully.'); } catch (error) { @@ -93,10 +32,10 @@ export class MessageLocalDataSourceService extends DexieRepository } } - async getLastMessageByRoomId(roomId: string): Promise> { + async getLastMessageByRoomId(roomId: string): Promise> { try { console.log({roomId}) - const lastMessage = await messageDataSource.message + const lastMessage = await chatDatabase.message .where('roomId') .equals(roomId) .reverse() @@ -108,10 +47,10 @@ export class MessageLocalDataSourceService extends DexieRepository } } - async deleteByMessageId(id: string): Promise> { + async deleteByMessageId(id: string): Promise> { try { console.log(id) - const lastMessage = await messageDataSource.message + const lastMessage = await chatDatabase.message .where('id') .equals(id).delete() @@ -124,10 +63,10 @@ export class MessageLocalDataSourceService extends DexieRepository async sendMessage(data: MessageInputDTO) { - (data as TableMessage).sending = true + (data as MessageTable).sending = true try { - const result = await messageDataSource.message.add(data) + const result = await chatDatabase.message.add(data) this.messageSubject.next({roomId: data.roomId}); return ok(result as number) } catch (e) { @@ -137,16 +76,12 @@ export class MessageLocalDataSourceService extends DexieRepository } - incomingSocketMessage() { - - } - // @ValidateSchema(tableSchema) async createMessage(data: MessageInputDTO) { try { - const result = await messageDataSource.message.add(data) + const result = await chatDatabase.message.add(data) this.messageSubject.next({roomId: data.roomId}); return ok(result) } catch (e) { @@ -158,7 +93,7 @@ export class MessageLocalDataSourceService extends DexieRepository async createManyMessage(data: MessageInputDTO[]) { try { - const result = await messageDataSource.message.bulkAdd(data) + const result = await chatDatabase.message.bulkAdd(data) this.messageSubject.next({roomId: data[0].roomId}); return ok(result) } catch (e) { @@ -172,7 +107,7 @@ export class MessageLocalDataSourceService extends DexieRepository console.log({id}); - const existingMessage = await messageDataSource.message + const existingMessage = await chatDatabase.message .where('id') .equals(id) .first(); @@ -190,10 +125,10 @@ export class MessageLocalDataSourceService extends DexieRepository } // not used - async updateByMessageId(data: TableMessage ) { + async updateByMessageId(data: MessageTable ) { try { - const result = await messageDataSource.message.update(data.id as any, data) + const result = await chatDatabase.message.update(data.id as any, data) return ok(result) } catch (e) { return err(false) @@ -202,7 +137,7 @@ export class MessageLocalDataSourceService extends DexieRepository } - async findOrUpdate(data: TableMessage) { + async findOrUpdate(data: MessageTable) { const findResult = await this.findMessageById(data.id) if(findResult.isOk()) { @@ -213,17 +148,17 @@ export class MessageLocalDataSourceService extends DexieRepository } getItems(roomId: string) { - return messageDataSource.message.where('roomId').equals(roomId).toArray() + return chatDatabase.message.where('roomId').equals(roomId).toArray() } getItemsLive(roomId: string) { - return liveQuery(() => messageDataSource.message.where('roomId').equals(roomId).sortBy('$id')) + return liveQuery(() => chatDatabase.message.where('roomId').equals(roomId).sortBy('$id')) } async findMessageById(id: string) { try { - const a = await messageDataSource.message.where('id').equals(id).first() + const a = await chatDatabase.message.where('id').equals(id).first() if(a) { return ok(a) @@ -238,9 +173,9 @@ export class MessageLocalDataSourceService extends DexieRepository } - subscribeToNewMessage(roomId: string): Observable { + subscribeToNewMessage(roomId: string): Observable { return this.messageSubject.pipe( - filter((message: TableMessage) => + filter((message: MessageTable) => message.roomId === roomId ) ) @@ -249,7 +184,7 @@ export class MessageLocalDataSourceService extends DexieRepository async getOfflineMessages () { try { - const allMessages = await messageDataSource.message + const allMessages = await chatDatabase.message .filter(msg => typeof msg.id !== 'string' && msg.sending == false) .toArray(); diff --git a/src/app/module/chat/data/data-source/room/room-memory-data-source.ts b/src/app/module/chat/data/data-source/room/room-memory-data-source.ts index 63dfea300..b064d8fcd 100644 --- a/src/app/module/chat/data/data-source/room/room-memory-data-source.ts +++ b/src/app/module/chat/data/data-source/room/room-memory-data-source.ts @@ -1,10 +1,10 @@ import { createAction, createFeatureSelector, createReducer, createSelector, on, props } from "@ngrx/store"; -import { TableRoom } from "./rooom-local-data-source.service"; import { RoomOutPutDTO } from "../../dto/room/roomOutputDTO"; +import { RoomTable } from "../../../infra/database/dexie/schema/room"; export interface ChatRoom { - [roomId: string]: TableRoom[]; + [roomId: string]: RoomTable[]; } export interface RoomRemoteDataSourceState { diff --git a/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts b/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts index 32a1433c2..e3dca759e 100644 --- a/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts +++ b/src/app/module/chat/data/data-source/room/rooom-local-data-source.service.ts @@ -5,72 +5,24 @@ import { err, ok, Result } from 'neverthrow'; import { z } from 'zod'; import { ValidateSchema } from 'src/app/services/decorators/validate-schema.decorator'; import { MemberListUPdateStatusInputDTO } from '../../../domain/use-case/socket/member-list-update-status-use-case.service'; +import { MemberTable } from '../../../infra/database/dexie/schema/members'; +import { chatDatabase } from '../../../infra/database/dexie/service'; +import { RoomTable, RoomTableSchema } from '../../../infra/database/dexie/schema/room'; +import { TypingTableSchema } from '../../../infra/database/dexie/schema/typing'; -const tableSchema = z.object({ - id: z.string(), - roomName: z.string(), - createdBy: z.object({ - wxUserId: z.number(), - wxFullName: z.string(), - wxeMail: z.string().email(), - userPhoto: z.string().nullable().optional()// api check - }), - createdAt: z.any(), - expirationDate: z.any().nullable(), -}) - -const TableMemberListSchema = z.object({ - $roomIdUserId: z.string().optional(), - id: z.string(), - roomId: z.string(), - wxUserId: z.number(), - wxFullName: z.string(), - wxeMail: z.string(), - userPhoto: z.string().nullable(), - joinAt: z.string(), - status: z.string(), - isAdmin: z.boolean() -}) - - -export const TypingSchema = z.object({ - id: z.string().optional(), - userId: z.string(), - roomId: z.string(), - entryDate: z.string() -}) - - -export type TableRoom = z.infer -export type TableMemberList = z.infer -export type TypingList = z.infer - -// Database declaration (move this to its own module also) -export const roomDataSource = new Dexie('FriendDatabase') as Dexie & { - room: EntityTable; - memberList: EntityTable; - typing: EntityTable; -}; - -roomDataSource.version(1).stores({ - room: 'id, createdBy, roomName, roomType, expirationDate, lastMessage', - memberList: '$roomIdUserId, userId, id, user, joinAt, roomId, status, wxUserId, isAdmin', - TypingList: '++id, userId, roomId, entryDate', -}); @Injectable({ providedIn: 'root' }) export class RoomLocalDataSourceService { - private baseUrl = 'https://gdapi-dev.dyndns.info/stage/api/v2/Chat'; // Your base URL constructor() {} - @ValidateSchema(TypingSchema) + @ValidateSchema(TypingTableSchema) async addUserTyping(data: any) { try { - const result = await roomDataSource.typing.add(data) + const result = await chatDatabase.typing.add(data) return ok(result) } catch (e) { return err(false) @@ -81,10 +33,10 @@ export class RoomLocalDataSourceService { } - @ValidateSchema(tableSchema) - async createRoom(data: TableRoom) { + @ValidateSchema(RoomTableSchema) + async createRoom(data: RoomTable) { try { - const result = await roomDataSource.room.add(data) + const result = await chatDatabase.room.add(data) return ok(result) } catch (e) { return err(false) @@ -94,7 +46,7 @@ export class RoomLocalDataSourceService { async deleteRoomById(id: string) { try { - const result = await roomDataSource.room.delete(id) + const result = await chatDatabase.room.delete(id) return ok(result) } catch (e) { return err(false) @@ -106,9 +58,9 @@ export class RoomLocalDataSourceService { return this.deleteRoomById(id) } - async updateRoom(data: TableRoom) { + async updateRoom(data: RoomTable) { try { - const result = await roomDataSource.room.update(data.id, data); + const result = await chatDatabase.room.update(data.id, data); return ok(result) } catch (e) { @@ -116,7 +68,7 @@ export class RoomLocalDataSourceService { } } - async createOrUpdateRoom(data: TableRoom) { + async createOrUpdateRoom(data: RoomTable) { const createResult = await this.createRoom(data) if(createResult.isOk()) { @@ -127,19 +79,19 @@ export class RoomLocalDataSourceService { } - async addMember(data: TableMemberList) { + async addMember(data: MemberTable) { try { data.$roomIdUserId = data.roomId + data.wxUserId - const result = await roomDataSource.memberList.add(data) + const result = await chatDatabase.members.add(data) return ok(result) } catch (e) { return err(false) } } - async updateMemberRole(data: TableMemberList) { - try { - const result = await roomDataSource.memberList.where({ + async updateMemberRole(data: MemberTable) { + try { + const result = await chatDatabase.members.where({ wxUserId:data.wxUserId, roomId: data.roomId, }).modify(data); @@ -152,10 +104,10 @@ export class RoomLocalDataSourceService { async updateMembersStatus(data: MemberListUPdateStatusInputDTO) { try { - await roomDataSource.memberList.toCollection().modify({ status: 'offline' }); + await chatDatabase.members.toCollection().modify({ status: 'offline' }); for (const item of data) { const wxUserId = item.value.userId; // Extract wxUserId - await roomDataSource.memberList.where('wxUserId').equals(wxUserId).modify({ status: 'online' }); + await chatDatabase.members.where('wxUserId').equals(wxUserId).modify({ status: 'online' }); } return ok(true) } catch (error) { @@ -167,7 +119,7 @@ export class RoomLocalDataSourceService { allMemberOnline(roomId:string) { return liveQuery(async () => { - const allMessages = await roomDataSource.memberList + const allMessages = await chatDatabase.members .where('roomId') .equals(roomId) .toArray(); @@ -179,10 +131,10 @@ export class RoomLocalDataSourceService { async removeMemberFromRoom($roomIdUserId): Promise> { try { - const member = await roomDataSource.memberList.where({ $roomIdUserId: $roomIdUserId }).first(); + const member = await chatDatabase.members.where({ $roomIdUserId: $roomIdUserId }).first(); if (member) { - const result = await ok(roomDataSource.memberList.delete($roomIdUserId)); + const result = await ok(chatDatabase.members.delete($roomIdUserId)); console.log(`Member with $roomIdUserId ${$roomIdUserId} removed from room ${member.roomId}.`); return result } else { @@ -197,7 +149,7 @@ export class RoomLocalDataSourceService { async getRoomById(id: any) { try { - const result = await roomDataSource.room.get(id) + const result = await chatDatabase.room.get(id) return ok(result) } catch (e) { return err(false) @@ -206,32 +158,32 @@ export class RoomLocalDataSourceService { async getRoomList() { - return await roomDataSource.room.toArray() + return await chatDatabase.room.toArray() } getMemberLive(data: {roomId, wxUserId}) { const $roomIdUserId = data.roomId + data.wxUserId - return liveQuery(() => roomDataSource.memberList.get($roomIdUserId)) as any; + return liveQuery(() => chatDatabase.members.get($roomIdUserId)) as any; } getItemsLive(): Observable { - return liveQuery(() => roomDataSource.room.toArray()) as any; + return liveQuery(() => chatDatabase.room.toArray()) as any; } getRoomByIdLive(id: any): Observable { - return liveQuery(() => roomDataSource.room.get(id)) as any; + return liveQuery(() => chatDatabase.room.get(id)) as any; } async getRoomMemberById(roomId: any) { - return await roomDataSource.memberList.where({roomId}).toArray() + return await chatDatabase.members.where({roomId}).toArray() } getRoomMemberByIdLive(roomId: any) { - return liveQuery(() => roomDataSource.memberList.where({roomId}).toArray()) + return liveQuery(() => chatDatabase.members.where({roomId}).toArray()) } getRoomMemberNoneAdminByIdLive(roomId: any) { return liveQuery(async() => { - const members = await roomDataSource.memberList.where({roomId}).toArray() + const members = await chatDatabase.members.where({roomId}).toArray() return members.filter(e => e.isAdmin != true) }) } diff --git a/src/app/module/chat/data/repository/message-respository.service.ts b/src/app/module/chat/data/repository/message-respository.service.ts index 05ed52dab..0721df706 100644 --- a/src/app/module/chat/data/repository/message-respository.service.ts +++ b/src/app/module/chat/data/repository/message-respository.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { MessageRemoteDataSourceService } from '../data-source/message/message-remote-data-source.service'; import { MessageLiveDataSourceService } from '../data-source/message/message-live-data-source.service'; -import { MessageLocalDataSourceService, TableMessage } from '../data-source/message/message-local-data-source.service'; +import { MessageLocalDataSourceService } from '../data-source/message/message-local-data-source.service'; import { SessionStore } from 'src/app/store/session.service'; import { SignalRService } from '../../infra/socket/signal-r.service'; import { v4 as uuidv4 } from 'uuid' @@ -13,6 +13,7 @@ import { MessageEntity } from '../../domain/entity/message'; import { InstanceId } from '../../domain/chat-service.service'; import { MessageMapper } from '../../domain/mapper/messageMapper'; import { MessageOutPutDataDTO } from '../dto/message/messageOutputDTO'; +import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message'; @Injectable({ @@ -55,7 +56,7 @@ export class MessageRepositoryService { delete sendMessageResult.value.sender } - let clone: TableMessage = { + let clone: MessageTable = { ...sendMessageResult.value, id: sendMessageResult.value.id, $id : localActionResult.value @@ -115,13 +116,13 @@ export class MessageRepositoryService { const { addedItems, changedItems } = messageListDetermineChanges(result.value.data, localResult) for(const message of changedItems) { - let clone: TableMessage = message + let clone: MessageTable = message clone.roomId = id await this.messageLocalDataSourceService.findOrUpdate(clone) } for(const message of addedItems) { - let clone: TableMessage = message + let clone: MessageTable = message clone.roomId = id } diff --git a/src/app/module/chat/data/service/sync-repository/sync-message-repository.service.ts b/src/app/module/chat/data/service/sync-repository/sync-message-repository.service.ts index 0df5ef032..a5e92b457 100644 --- a/src/app/module/chat/data/service/sync-repository/sync-message-repository.service.ts +++ b/src/app/module/chat/data/service/sync-repository/sync-message-repository.service.ts @@ -1,12 +1,13 @@ import { Injectable } from '@angular/core'; import { SignalRService } from '../../../infra/socket/signal-r.service'; import { MessageLiveDataSourceService } from '../../data-source/message/message-live-data-source.service'; -import { MessageLocalDataSourceService, TableMessage } from '../../data-source/message/message-local-data-source.service'; +import { MessageLocalDataSourceService } from '../../data-source/message/message-local-data-source.service'; import { MessageRemoteDataSourceService } from '../../data-source/message/message-remote-data-source.service'; import { InstanceId } from '../../../domain/chat-service.service'; import { v4 as uuidv4 } from 'uuid' import { MessageMapper } from 'src/app/module/chat/domain/mapper/messageMapper' import { MessageOutPutDataDTO } from '../../dto/message/messageOutputDTO'; +import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message'; @Injectable({ providedIn: 'root' @@ -44,7 +45,7 @@ export class SyncMessageRepositoryService { delete sendMessageResult.value.sender } - let clone: TableMessage = { + let clone: MessageTable = { ...sendMessageResult.value, id: sendMessageResult.value.id, $id : message.$id diff --git a/src/app/module/chat/domain/mapper/memberLIstMapper.ts b/src/app/module/chat/domain/mapper/memberLIstMapper.ts index 1d904befe..f950ccef3 100644 --- a/src/app/module/chat/domain/mapper/memberLIstMapper.ts +++ b/src/app/module/chat/domain/mapper/memberLIstMapper.ts @@ -1,7 +1,8 @@ -import { TableMemberList } from "../../data/data-source/room/rooom-local-data-source.service"; -import { RoomByIdMemberItemOutputDTO } from "../../data/dto/room/roomByIdOutputDTO"; -export function MemberListMapper(outputDto: RoomByIdMemberItemOutputDTO, roomId: string): TableMemberList { +import { RoomByIdMemberItemOutputDTO } from "../../data/dto/room/roomByIdOutputDTO"; +import { MemberTable } from "../../infra/database/dexie/schema/members"; + +export function MemberListMapper(outputDto: RoomByIdMemberItemOutputDTO, roomId: string): MemberTable { return { roomId: roomId, wxUserId: outputDto.user.wxUserId, diff --git a/src/app/module/chat/infra/database/dexie/schema/members.ts b/src/app/module/chat/infra/database/dexie/schema/members.ts new file mode 100644 index 000000000..aeb1dcade --- /dev/null +++ b/src/app/module/chat/infra/database/dexie/schema/members.ts @@ -0,0 +1,19 @@ +import { z } from "zod"; +import { EntityTable } from 'Dexie'; + +export const MemberTableSchema = z.object({ + $roomIdUserId: z.string().optional(), + id: z.string(), + roomId: z.string(), + wxUserId: z.number(), + wxFullName: z.string(), + wxeMail: z.string(), + userPhoto: z.string().nullable(), + joinAt: z.string(), + status: z.string(), + isAdmin: z.boolean() +}) + +export type MemberTable = z.infer +export type DexieMembersTableSchema = EntityTable; +export const MemberTableColumn = '$roomIdUserId, userId, id, user, joinAt, roomId, status, wxUserId, isAdmin' diff --git a/src/app/module/chat/infra/database/dexie/schema/message.ts b/src/app/module/chat/infra/database/dexie/schema/message.ts new file mode 100644 index 000000000..05312001a --- /dev/null +++ b/src/app/module/chat/infra/database/dexie/schema/message.ts @@ -0,0 +1,31 @@ +import { z } from "zod"; +import { EntityTable } from 'Dexie'; + +export const MessageTable = z.object({ + $id: z.number().optional(), + id: z.string().optional(), + roomId: z.string().uuid(), + message: z.string(), + messageType: z.number(), + canEdit: z.boolean(), + oneShot: z.boolean(), + sentAt: z.string().optional(), + requireUnlock: z.boolean(), + sender: z.object({ + wxUserId: z.number(), + wxFullName: z.string(), + wxeMail: z.string(), + userPhoto: z.string(), + }), + sending: z.boolean().optional(), + reaction: z.object({ + id: z.string(), + reactedAt: z.string(), + reaction: z.string(), + sender: z.object({}), + }).array() +}) + +export type MessageTable = z.infer +export type DexieMessageTable = EntityTable; +export const messageTableColumn = '++id, roomId, senderId, message, messageType, canEdit, oneShot, requireUnlock' diff --git a/src/app/module/chat/infra/database/dexie/schema/room.ts b/src/app/module/chat/infra/database/dexie/schema/room.ts new file mode 100644 index 000000000..e478dbe95 --- /dev/null +++ b/src/app/module/chat/infra/database/dexie/schema/room.ts @@ -0,0 +1,19 @@ +import { z } from "zod"; +import { EntityTable } from 'Dexie'; + +export const RoomTableSchema = z.object({ + id: z.string(), + roomName: z.string(), + createdBy: z.object({ + wxUserId: z.number(), + wxFullName: z.string(), + wxeMail: z.string().email(), + userPhoto: z.string().nullable().optional()// api check + }), + createdAt: z.any(), + expirationDate: z.any().nullable(), +}) + +export type RoomTable = z.infer +export type DexieRoomsTableSchema = EntityTable; +export const RoomTableColumn = 'id, createdBy, roomName, roomType, expirationDate, lastMessage' diff --git a/src/app/module/chat/infra/database/dexie/schema/typing.ts b/src/app/module/chat/infra/database/dexie/schema/typing.ts new file mode 100644 index 000000000..7f0c72b4c --- /dev/null +++ b/src/app/module/chat/infra/database/dexie/schema/typing.ts @@ -0,0 +1,13 @@ +import { z } from "zod"; +import { EntityTable } from 'Dexie'; + +export const TypingTableSchema = z.object({ + id: z.string().optional(), + userId: z.string(), + roomId: z.string(), + entryDate: z.string() +}) + +export type TypingTable = z.infer +export type DexieTypingsTableSchema = EntityTable; +export const TypingTableColumn = '++id, userId, roomId, entryDate' diff --git a/src/app/module/chat/infra/database/dexie/service.ts b/src/app/module/chat/infra/database/dexie/service.ts new file mode 100644 index 000000000..c2810a6b7 --- /dev/null +++ b/src/app/module/chat/infra/database/dexie/service.ts @@ -0,0 +1,21 @@ + +import { Dexie, EntityTable, liveQuery } from 'Dexie'; +import { DexieMessageTable, messageTableColumn, MessageTable } from './schema/message'; +import { DexieMembersTableSchema, MemberTableColumn } from './schema/members'; +import { DexieRoomsTableSchema, RoomTableColumn } from './schema/room'; +import { DexieTypingsTableSchema, TypingTableColumn } from './schema/typing'; + +// Database declaration (move this to its own module also) +export const chatDatabase = new Dexie('chat-database') as Dexie & { + message: DexieMessageTable, + members: DexieMembersTableSchema, + room: DexieRoomsTableSchema, + typing: DexieTypingsTableSchema +}; + +chatDatabase.version(1).stores({ + message: messageTableColumn, + members: MemberTableColumn, + room: RoomTableColumn, + typing: TypingTableColumn +}); diff --git a/src/app/shared/chat/messages/messages.page.ts b/src/app/shared/chat/messages/messages.page.ts index 705f58b7a..ffdbf9dd7 100644 --- a/src/app/shared/chat/messages/messages.page.ts +++ b/src/app/shared/chat/messages/messages.page.ts @@ -36,8 +36,7 @@ import { Observable as DexieObservable } from 'Dexie'; import { Observable, Subscription } from 'rxjs'; import { MessageRepositoryService } from 'src/app/module/chat/data/repository/message-respository.service' import { RoomRepositoryService } from 'src/app/module/chat/data/repository/room-repository.service' -import { TableMessage } from 'src/app/module/chat/data/data-source/message/message-local-data-source.service'; -import { TableMemberList } from 'src/app/module/chat/data/data-source/room/rooom-local-data-source.service'; +import { MessageTable } from 'src/app/module/chat/infra/database/dexie/schema/message'; import { MessageInputDTO } from 'src/app/module/chat/data/dto/message/messageInputDtO'; import { RoomListItemOutPutDTO } from 'src/app/module/chat/data/dto/room/roomListOutputDTO'; import { UserTypingServiceRepository } from 'src/app/module/chat/data/repository/user-typing-repository.service'; @@ -46,6 +45,7 @@ import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.serv import { EditMessagePage } from 'src/app/modals/edit-message/edit-message.page'; import { tap } from 'rxjs/operators'; import { MessageEntity } from 'src/app/module/chat/domain/entity/message'; +import { MemberTable } from 'src/app/module/chat/infra/database/dexie/schema/members'; const IMAGE_DIR = 'stored-images'; @@ -125,8 +125,8 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy roomData$: DexieObservable roomStatus$: DexieObservable - roomMessage$: DexieObservable - roomMembers$: DexieObservable + roomMessage$: DexieObservable + roomMembers$: DexieObservable //userTyping$: DexieObservable userTyping$: UserTypingList[] | undefined newMessagesStream!: Subscription