separate database from source data

This commit is contained in:
Peter Maquiran
2024-08-07 19:30:20 +01:00
parent 75a8822e57
commit 159eb8d350
17 changed files with 189 additions and 197 deletions
@@ -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<TableMemberList[] | undefined>
roomMembers$: DexieObservable<MemberTable[] | undefined>
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,
@@ -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[]) {
@@ -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]));
@@ -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=> {
@@ -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<typeof TableMemberListSchema>
export type IMemberTable = z.infer<typeof MemberTableSchema>
type ITableMemberListSchema = EntityTable<ITableMemberList, '$roomIdUserId'>
type IMemberTableSchema = EntityTable<IMemberTable, '$roomIdUserId'>
// Database declaration (move this to its own module also)
export const roomMemberList = new Dexie('roomMemberList') as Dexie & {
memberList: EntityTable<ITableMemberList, '$roomIdUserId'>;
memberList: EntityTable<IMemberTable, '$roomIdUserId'>;
};
roomMemberList.version(1).stores({
@@ -34,7 +34,7 @@ roomMemberList.version(1).stores({
@Injectable({
providedIn: 'root'
})
export class MemberListLocalDataSourceService extends DexieRepository<ITableMemberList> {
export class MemberListLocalDataSourceService extends DexieRepository<IMemberTable> {
constructor() {
super(roomMemberList.memberList);
@@ -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<typeof tableSchema>
// Database declaration (move this to its own module also)
export const messageDataSource = new Dexie('chat-message') as Dexie & {
message: EntityTable<TableMessage, '$id'>;
};
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<TableMessage> {
export class MessageLocalDataSourceService extends DexieRepository<MessageTable> {
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<TableMessage>
}
}
async getLastMessageByRoomId(roomId: string): Promise<Result<undefined|TableMessage, any>> {
async getLastMessageByRoomId(roomId: string): Promise<Result<undefined|MessageTable, any>> {
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<TableMessage>
}
}
async deleteByMessageId(id: string): Promise<Result<undefined|TableMessage, any>> {
async deleteByMessageId(id: string): Promise<Result<undefined|MessageTable, any>> {
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<TableMessage>
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<TableMessage>
}
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<TableMessage>
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<TableMessage>
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<TableMessage>
}
// 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<TableMessage>
}
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<TableMessage>
}
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<TableMessage>
}
subscribeToNewMessage(roomId: string): Observable<TableMessage> {
subscribeToNewMessage(roomId: string): Observable<MessageTable> {
return this.messageSubject.pipe(
filter((message: TableMessage) =>
filter((message: MessageTable) =>
message.roomId === roomId
)
)
@@ -249,7 +184,7 @@ export class MessageLocalDataSourceService extends DexieRepository<TableMessage>
async getOfflineMessages () {
try {
const allMessages = await messageDataSource.message
const allMessages = await chatDatabase.message
.filter(msg => typeof msg.id !== 'string' && msg.sending == false)
.toArray();
@@ -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 {
@@ -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<typeof tableSchema>
export type TableMemberList = z.infer<typeof TableMemberListSchema>
export type TypingList = z.infer<typeof TypingSchema>
// Database declaration (move this to its own module also)
export const roomDataSource = new Dexie('FriendDatabase') as Dexie & {
room: EntityTable<TableRoom, 'id'>;
memberList: EntityTable<TableMemberList, '$roomIdUserId'>;
typing: EntityTable<TableMemberList, '$roomIdUserId'>;
};
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<Result<any ,any>> {
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<RoomListOutPutDTO[]> {
return liveQuery(() => roomDataSource.room.toArray()) as any;
return liveQuery(() => chatDatabase.room.toArray()) as any;
}
getRoomByIdLive(id: any): Observable<RoomListItemOutPutDTO | undefined> {
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)
})
}
@@ -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
}
@@ -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
@@ -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,
@@ -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<typeof MemberTableSchema>
export type DexieMembersTableSchema = EntityTable<MemberTable, '$roomIdUserId'>;
export const MemberTableColumn = '$roomIdUserId, userId, id, user, joinAt, roomId, status, wxUserId, isAdmin'
@@ -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<typeof MessageTable>
export type DexieMessageTable = EntityTable<MessageTable, '$id'>;
export const messageTableColumn = '++id, roomId, senderId, message, messageType, canEdit, oneShot, requireUnlock'
@@ -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<typeof RoomTableSchema>
export type DexieRoomsTableSchema = EntityTable<RoomTable, 'id'>;
export const RoomTableColumn = 'id, createdBy, roomName, roomType, expirationDate, lastMessage'
@@ -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<typeof TypingTableSchema>
export type DexieTypingsTableSchema = EntityTable<TypingTable, 'id'>;
export const TypingTableColumn = '++id, userId, roomId, entryDate'
@@ -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
});
@@ -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<RoomListItemOutPutDTO | undefined>
roomStatus$: DexieObservable<Boolean >
roomMessage$: DexieObservable<TableMessage[]>
roomMembers$: DexieObservable<TableMemberList[] | undefined>
roomMessage$: DexieObservable<MessageTable[]>
roomMembers$: DexieObservable<MemberTable[] | undefined>
//userTyping$: DexieObservable<UserTypingList[] | undefined>
userTyping$: UserTypingList[] | undefined
newMessagesStream!: Subscription