Chore: Migrate updateMessages to Typescript (#3715)
This commit is contained in:
parent
ed716396d0
commit
f51ec9ef0c
|
@ -54,7 +54,7 @@ export interface ILastMessage {
|
|||
}
|
||||
|
||||
export interface IMessage {
|
||||
_id?: string;
|
||||
_id: string;
|
||||
msg?: string;
|
||||
t?: SubscriptionType;
|
||||
ts: Date;
|
||||
|
|
|
@ -73,6 +73,7 @@ export interface IThread {
|
|||
autoTranslate?: boolean;
|
||||
translations?: any;
|
||||
e2e?: string;
|
||||
subscription: { id: string };
|
||||
}
|
||||
|
||||
export type TThreadModel = IThread & Model;
|
||||
|
|
|
@ -38,7 +38,7 @@ export interface IThreadMessage {
|
|||
autoTranslate?: boolean;
|
||||
translations?: ITranslations[];
|
||||
e2e?: string;
|
||||
subscription?: { id: string };
|
||||
subscription: { id: string };
|
||||
}
|
||||
|
||||
export type TThreadMessageModel = IThreadMessage & Model;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import database from '..';
|
||||
import { TAppDatabase } from '../interfaces';
|
||||
import { SUBSCRIPTIONS_TABLE } from '../model/Subscription';
|
||||
|
||||
const getCollection = db => db.get(SUBSCRIPTIONS_TABLE);
|
||||
const getCollection = (db: TAppDatabase) => db.get(SUBSCRIPTIONS_TABLE);
|
||||
|
||||
export const getSubscriptionByRoomId = async rid => {
|
||||
export const getSubscriptionByRoomId = async (rid: string) => {
|
||||
const db = database.active;
|
||||
const subCollection = getCollection(db);
|
||||
try {
|
|
@ -1,174 +0,0 @@
|
|||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
|
||||
import log from '../../utils/log';
|
||||
import database from '../database';
|
||||
import { Encryption } from '../encryption';
|
||||
import { MESSAGE_TYPE_ANY_LOAD } from '../../constants/messageTypeLoad';
|
||||
import { generateLoadMoreId } from '../utils';
|
||||
import protectedFunction from './helpers/protectedFunction';
|
||||
import buildMessage from './helpers/buildMessage';
|
||||
|
||||
export default function updateMessages({ rid, update = [], remove = [], loaderItem }) {
|
||||
try {
|
||||
if (!((update && update.length) || (remove && remove.length))) {
|
||||
return;
|
||||
}
|
||||
const db = database.active;
|
||||
return db.action(async () => {
|
||||
// Decrypt these messages
|
||||
update = await Encryption.decryptMessages(update);
|
||||
const subCollection = db.get('subscriptions');
|
||||
let sub;
|
||||
try {
|
||||
sub = await subCollection.find(rid);
|
||||
} catch (error) {
|
||||
sub = { id: rid };
|
||||
log(new Error('updateMessages: subscription not found'));
|
||||
}
|
||||
|
||||
const messagesIds = [...update.map(m => m._id), ...remove.map(m => m._id)];
|
||||
const msgCollection = db.get('messages');
|
||||
const threadCollection = db.get('threads');
|
||||
const threadMessagesCollection = db.get('thread_messages');
|
||||
const allMessagesRecords = await msgCollection
|
||||
.query(Q.where('rid', rid), Q.or(Q.where('id', Q.oneOf(messagesIds)), Q.where('t', Q.oneOf(MESSAGE_TYPE_ANY_LOAD))))
|
||||
.fetch();
|
||||
const allThreadsRecords = await threadCollection.query(Q.where('rid', rid), Q.where('id', Q.oneOf(messagesIds))).fetch();
|
||||
const allThreadMessagesRecords = await threadMessagesCollection
|
||||
.query(Q.where('subscription_id', rid), Q.where('id', Q.oneOf(messagesIds)))
|
||||
.fetch();
|
||||
|
||||
update = update.map(m => buildMessage(m));
|
||||
|
||||
// filter messages
|
||||
let msgsToCreate = update.filter(i1 => !allMessagesRecords.find(i2 => i1._id === i2.id));
|
||||
let msgsToUpdate = allMessagesRecords.filter(i1 => update.find(i2 => i1.id === i2._id));
|
||||
|
||||
// filter threads
|
||||
const allThreads = update.filter(m => m.tlm);
|
||||
let threadsToCreate = allThreads.filter(i1 => !allThreadsRecords.find(i2 => i1._id === i2.id));
|
||||
let threadsToUpdate = allThreadsRecords.filter(i1 => allThreads.find(i2 => i1.id === i2._id));
|
||||
|
||||
// filter thread messages
|
||||
const allThreadMessages = update.filter(m => m.tmid);
|
||||
let threadMessagesToCreate = allThreadMessages.filter(i1 => !allThreadMessagesRecords.find(i2 => i1._id === i2.id));
|
||||
let threadMessagesToUpdate = allThreadMessagesRecords.filter(i1 => allThreadMessages.find(i2 => i1.id === i2._id));
|
||||
|
||||
// filter loaders to delete
|
||||
let loadersToDelete = allMessagesRecords.filter(i1 => update.find(i2 => i1.id === generateLoadMoreId(i2._id)));
|
||||
|
||||
// Delete
|
||||
let msgsToDelete = [];
|
||||
let threadsToDelete = [];
|
||||
let threadMessagesToDelete = [];
|
||||
if (remove && remove.length) {
|
||||
msgsToDelete = allMessagesRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||
msgsToDelete = msgsToDelete.map(m => m.prepareDestroyPermanently());
|
||||
threadsToDelete = allThreadsRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||
threadsToDelete = threadsToDelete.map(t => t.prepareDestroyPermanently());
|
||||
threadMessagesToDelete = allThreadMessagesRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||
threadMessagesToDelete = threadMessagesToDelete.map(tm => tm.prepareDestroyPermanently());
|
||||
}
|
||||
|
||||
// Delete loaders
|
||||
loadersToDelete = loadersToDelete.map(m => m.prepareDestroyPermanently());
|
||||
if (loaderItem) {
|
||||
loadersToDelete.push(loaderItem.prepareDestroyPermanently());
|
||||
}
|
||||
|
||||
// Create
|
||||
msgsToCreate = msgsToCreate.map(message =>
|
||||
msgCollection.prepareCreate(
|
||||
protectedFunction(m => {
|
||||
m._raw = sanitizedRaw({ id: message._id }, msgCollection.schema);
|
||||
m.subscription.id = sub.id;
|
||||
Object.assign(m, message);
|
||||
})
|
||||
)
|
||||
);
|
||||
threadsToCreate = threadsToCreate.map(thread =>
|
||||
threadCollection.prepareCreate(
|
||||
protectedFunction(t => {
|
||||
t._raw = sanitizedRaw({ id: thread._id }, threadCollection.schema);
|
||||
t.subscription.id = sub.id;
|
||||
Object.assign(t, thread);
|
||||
})
|
||||
)
|
||||
);
|
||||
threadMessagesToCreate = threadMessagesToCreate.map(threadMessage =>
|
||||
threadMessagesCollection.prepareCreate(
|
||||
protectedFunction(tm => {
|
||||
tm._raw = sanitizedRaw({ id: threadMessage._id }, threadMessagesCollection.schema);
|
||||
Object.assign(tm, threadMessage);
|
||||
tm.subscription.id = sub.id;
|
||||
tm.rid = threadMessage.tmid;
|
||||
delete threadMessage.tmid;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// Update
|
||||
msgsToUpdate = msgsToUpdate.map(message => {
|
||||
const newMessage = update.find(m => m._id === message.id);
|
||||
try {
|
||||
return message.prepareUpdate(
|
||||
protectedFunction(m => {
|
||||
Object.assign(m, newMessage);
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
threadsToUpdate = threadsToUpdate.map(thread => {
|
||||
const newThread = allThreads.find(t => t._id === thread.id);
|
||||
try {
|
||||
return thread.prepareUpdate(
|
||||
protectedFunction(t => {
|
||||
Object.assign(t, newThread);
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
threadMessagesToUpdate = threadMessagesToUpdate.map(threadMessage => {
|
||||
const newThreadMessage = allThreadMessages.find(t => t._id === threadMessage.id);
|
||||
try {
|
||||
return threadMessage.prepareUpdate(
|
||||
protectedFunction(tm => {
|
||||
Object.assign(tm, newThreadMessage);
|
||||
tm.rid = threadMessage.tmid;
|
||||
delete threadMessage.tmid;
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
const allRecords = [
|
||||
...msgsToCreate,
|
||||
...msgsToUpdate,
|
||||
...msgsToDelete,
|
||||
...threadsToCreate,
|
||||
...threadsToUpdate,
|
||||
...threadsToDelete,
|
||||
...threadMessagesToCreate,
|
||||
...threadMessagesToUpdate,
|
||||
...threadMessagesToDelete,
|
||||
...loadersToDelete
|
||||
];
|
||||
|
||||
try {
|
||||
await db.batch(...allRecords);
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
return allRecords.length;
|
||||
});
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
|
||||
import database from '../database';
|
||||
import { Encryption } from '../encryption';
|
||||
import { MESSAGE_TYPE_ANY_LOAD } from '../../constants/messageTypeLoad';
|
||||
import { generateLoadMoreId } from '../utils';
|
||||
import protectedFunction from './helpers/protectedFunction';
|
||||
import buildMessage from './helpers/buildMessage';
|
||||
import { IMessage, TMessageModel, TThreadMessageModel, TThreadModel } from '../../definitions';
|
||||
import { getSubscriptionByRoomId } from '../database/services/Subscription';
|
||||
|
||||
interface IUpdateMessages {
|
||||
rid: string;
|
||||
update: IMessage[];
|
||||
remove: IMessage[];
|
||||
loaderItem?: TMessageModel;
|
||||
}
|
||||
|
||||
export default async function updateMessages({
|
||||
rid,
|
||||
update = [],
|
||||
remove = [],
|
||||
loaderItem
|
||||
}: IUpdateMessages): Promise<number | void> {
|
||||
if (!((update && update.length) || (remove && remove.length))) {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
|
||||
const sub = await getSubscriptionByRoomId(rid);
|
||||
if (!sub) {
|
||||
throw new Error('updateMessages: subscription not found');
|
||||
}
|
||||
|
||||
const db = database.active;
|
||||
return db.write(async () => {
|
||||
// Decrypt these messages
|
||||
update = await Encryption.decryptMessages(update);
|
||||
|
||||
const messagesIds: string[] = [...update.map(m => m._id), ...remove.map(m => m._id)];
|
||||
const msgCollection = db.get('messages');
|
||||
const threadCollection = db.get('threads');
|
||||
const threadMessagesCollection = db.get('thread_messages');
|
||||
const allMessagesRecords = await msgCollection
|
||||
.query(Q.where('rid', rid), Q.or(Q.where('id', Q.oneOf(messagesIds)), Q.where('t', Q.oneOf(MESSAGE_TYPE_ANY_LOAD))))
|
||||
.fetch();
|
||||
const allThreadsRecords = await threadCollection.query(Q.where('rid', rid), Q.where('id', Q.oneOf(messagesIds))).fetch();
|
||||
const allThreadMessagesRecords = await threadMessagesCollection
|
||||
.query(Q.where('subscription_id', rid), Q.where('id', Q.oneOf(messagesIds)))
|
||||
.fetch();
|
||||
|
||||
update = update.map(m => buildMessage(m));
|
||||
|
||||
// filter loaders to delete
|
||||
let loadersToDelete: TMessageModel[] = allMessagesRecords.filter(i1 =>
|
||||
update.find(i2 => i1.id === generateLoadMoreId(i2._id))
|
||||
);
|
||||
|
||||
// Delete
|
||||
let msgsToDelete: TMessageModel[] = [];
|
||||
let threadsToDelete: TThreadModel[] = [];
|
||||
let threadMessagesToDelete: TThreadMessageModel[] = [];
|
||||
if (remove && remove.length) {
|
||||
msgsToDelete = allMessagesRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||
msgsToDelete = msgsToDelete.map(m => m.prepareDestroyPermanently());
|
||||
threadsToDelete = allThreadsRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||
threadsToDelete = threadsToDelete.map(t => t.prepareDestroyPermanently());
|
||||
threadMessagesToDelete = allThreadMessagesRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||
threadMessagesToDelete = threadMessagesToDelete.map(tm => tm.prepareDestroyPermanently());
|
||||
}
|
||||
|
||||
// Delete loaders
|
||||
loadersToDelete = loadersToDelete.map(m => m.prepareDestroyPermanently());
|
||||
if (loaderItem) {
|
||||
loadersToDelete.push(loaderItem.prepareDestroyPermanently());
|
||||
}
|
||||
|
||||
// filter messages
|
||||
const filteredMsgsToCreate = update.filter(i1 => !allMessagesRecords.find(i2 => i1._id === i2.id));
|
||||
const filteredMsgsToUpdate = allMessagesRecords.filter(i1 => update.find(i2 => i1.id === i2._id));
|
||||
|
||||
// filter threads
|
||||
const allThreads = update.filter(m => m.tlm);
|
||||
const filteredThreadsToCreate = allThreads.filter(i1 => !allThreadsRecords.find(i2 => i1._id === i2.id));
|
||||
const filteredThreadsToUpdate = allThreadsRecords.filter(i1 => allThreads.find(i2 => i1.id === i2._id));
|
||||
|
||||
// filter thread messages
|
||||
const allThreadMessages = update.filter(m => m.tmid);
|
||||
const filteredThreadMessagesToCreate = allThreadMessages.filter(i1 => !allThreadMessagesRecords.find(i2 => i1._id === i2.id));
|
||||
const filteredThreadMessagesToUpdate = allThreadMessagesRecords.filter(i1 => allThreadMessages.find(i2 => i1.id === i2._id));
|
||||
|
||||
// Create
|
||||
const msgsToCreate = filteredMsgsToCreate.map(message =>
|
||||
msgCollection.prepareCreate(
|
||||
protectedFunction((m: TMessageModel) => {
|
||||
m._raw = sanitizedRaw({ id: message._id }, msgCollection.schema);
|
||||
m.subscription.id = sub.id;
|
||||
Object.assign(m, message);
|
||||
})
|
||||
)
|
||||
);
|
||||
const threadsToCreate = filteredThreadsToCreate.map(thread =>
|
||||
threadCollection.prepareCreate(
|
||||
protectedFunction((t: TThreadModel) => {
|
||||
t._raw = sanitizedRaw({ id: thread._id }, threadCollection.schema);
|
||||
t.subscription.id = sub.id;
|
||||
Object.assign(t, thread);
|
||||
})
|
||||
)
|
||||
);
|
||||
const threadMessagesToCreate = filteredThreadMessagesToCreate.map(threadMessage =>
|
||||
threadMessagesCollection.prepareCreate(
|
||||
protectedFunction((tm: TThreadMessageModel) => {
|
||||
tm._raw = sanitizedRaw({ id: threadMessage._id }, threadMessagesCollection.schema);
|
||||
Object.assign(tm, threadMessage);
|
||||
tm.subscription.id = sub.id;
|
||||
if (threadMessage.tmid) {
|
||||
tm.rid = threadMessage.tmid;
|
||||
}
|
||||
delete threadMessage.tmid;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// Update
|
||||
const msgsToUpdate = filteredMsgsToUpdate.map(message => {
|
||||
const newMessage = update.find(m => m._id === message.id);
|
||||
try {
|
||||
return message.prepareUpdate(
|
||||
protectedFunction((m: TMessageModel) => {
|
||||
Object.assign(m, newMessage);
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
const threadsToUpdate = filteredThreadsToUpdate.map(thread => {
|
||||
const newThread = allThreads.find(t => t._id === thread.id);
|
||||
try {
|
||||
return thread.prepareUpdate(
|
||||
protectedFunction((t: TThreadModel) => {
|
||||
Object.assign(t, newThread);
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
const threadMessagesToUpdate = filteredThreadMessagesToUpdate.map(threadMessage => {
|
||||
const newThreadMessage = allThreadMessages.find(t => t._id === threadMessage.id);
|
||||
try {
|
||||
return threadMessage.prepareUpdate(
|
||||
protectedFunction((tm: TThreadMessageModel) => {
|
||||
Object.assign(tm, newThreadMessage);
|
||||
if (threadMessage.tmid) {
|
||||
tm.rid = threadMessage.tmid;
|
||||
}
|
||||
delete threadMessage.tmid;
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
const allRecords = [
|
||||
...msgsToDelete,
|
||||
...threadsToDelete,
|
||||
...threadMessagesToDelete,
|
||||
...loadersToDelete,
|
||||
...msgsToCreate,
|
||||
...msgsToUpdate,
|
||||
...threadsToCreate,
|
||||
...threadsToUpdate,
|
||||
...threadMessagesToCreate,
|
||||
...threadMessagesToUpdate
|
||||
];
|
||||
|
||||
await db.batch(...allRecords);
|
||||
return allRecords.length;
|
||||
});
|
||||
}
|
|
@ -191,6 +191,9 @@ const checkServer = async server => {
|
|||
await waitFor(element(by.label(label)))
|
||||
.toBeVisible()
|
||||
.withTimeout(10000);
|
||||
await waitFor(element(by.id('sidebar-close-drawer')))
|
||||
.toBeVisible()
|
||||
.withTimeout(10000);
|
||||
await element(by.id('sidebar-close-drawer')).tap();
|
||||
};
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ describe('Deep linking', () => {
|
|||
});
|
||||
await waitFor(element(by[textMatcher]("You've been logged out by the server. Please log in again.")))
|
||||
.toExist()
|
||||
.withTimeout(10000); // TODO: we need to improve this message
|
||||
.withTimeout(30000); // TODO: we need to improve this message
|
||||
});
|
||||
|
||||
const authAndNavigate = async () => {
|
||||
|
@ -97,7 +97,7 @@ describe('Deep linking', () => {
|
|||
});
|
||||
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
||||
.toExist()
|
||||
.withTimeout(10000);
|
||||
.withTimeout(30000);
|
||||
});
|
||||
|
||||
it('should navigate to the thread using path', async () => {
|
||||
|
@ -108,7 +108,7 @@ describe('Deep linking', () => {
|
|||
});
|
||||
await waitFor(element(by.id(`room-view-title-${threadMessage}`)))
|
||||
.toExist()
|
||||
.withTimeout(10000);
|
||||
.withTimeout(30000);
|
||||
});
|
||||
|
||||
it('should navigate to the room using rid', async () => {
|
||||
|
@ -120,7 +120,7 @@ describe('Deep linking', () => {
|
|||
});
|
||||
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
||||
.toExist()
|
||||
.withTimeout(15000);
|
||||
.withTimeout(30000);
|
||||
await tapBack();
|
||||
});
|
||||
});
|
||||
|
@ -144,7 +144,7 @@ describe('Deep linking', () => {
|
|||
});
|
||||
await waitFor(element(by.id(`room-view-title-${data.groups.private.name}`)))
|
||||
.toExist()
|
||||
.withTimeout(10000);
|
||||
.withTimeout(30000);
|
||||
});
|
||||
|
||||
it('should add a not existing server and fallback to the previous one', async () => {
|
||||
|
@ -155,7 +155,7 @@ describe('Deep linking', () => {
|
|||
});
|
||||
await waitFor(element(by.id('rooms-list-view')))
|
||||
.toBeVisible()
|
||||
.withTimeout(10000);
|
||||
.withTimeout(30000);
|
||||
await checkServer(data.server);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue