diff --git a/app/database/models/server/team.ts b/app/database/models/server/team.ts index 74cb563849..965052fb81 100644 --- a/app/database/models/server/team.ts +++ b/app/database/models/server/team.ts @@ -110,19 +110,18 @@ export default class TeamModel extends Model implements TeamModelInterface { /** teamSearchHistories : All the searches performed on this team */ @children(TEAM_SEARCH_HISTORY) teamSearchHistories!: Query; - /** threads : All threads belonging to a team */ - @lazy threads = this.collections.get(THREAD).query( - Q.on(THREADS_IN_TEAM, 'team_id', this.id), - ); - /** threads : Threads list belonging to a team */ - @lazy threadsList = this.threads.extend( - Q.where('loadedInGlobalThreads', true), + @lazy threadsList = this.collections.get(THREAD).query( + Q.on(THREADS_IN_TEAM, Q.and( + Q.where('team_id', this.id), + Q.where('loadedInGlobalThreads', true), + )), Q.sortBy('last_reply_at', Q.desc), ); /** unreadThreadsList : Unread threads list belonging to a team */ - @lazy unreadThreadsList = this.threads.extend( + @lazy unreadThreadsList = this.collections.get(THREAD).query( + Q.on(THREADS_IN_TEAM, 'team_id', this.id), Q.where('unread_replies', Q.gt(0)), Q.sortBy('last_reply_at', Q.desc), ); diff --git a/app/database/models/server/thread.ts b/app/database/models/server/thread.ts index 3aa7ef2d84..a79406d8db 100644 --- a/app/database/models/server/thread.ts +++ b/app/database/models/server/thread.ts @@ -52,9 +52,6 @@ export default class ThreadModel extends Model implements ThreadModelInterface { /** unread_mentions : The number of mentions that have not been read by the user. */ @field('unread_mentions') unreadMentions!: number; - /** loaded_in_global_threads : Flag to differentiate the unread threads loaded for showing unread counts/mentions */ - @field('loaded_in_global_threads') loadedInGlobalThreads!: boolean; - /** participants : All the participants associated with this Thread */ @children(THREAD_PARTICIPANT) participants!: Query; diff --git a/app/database/models/server/thread_in_team.ts b/app/database/models/server/thread_in_team.ts index 4d6e6ee930..6bc8531d30 100644 --- a/app/database/models/server/thread_in_team.ts +++ b/app/database/models/server/thread_in_team.ts @@ -37,6 +37,9 @@ export default class ThreadInTeamModel extends Model implements ThreadInTeamMode /** team_id: Associated team identifier */ @field('team_id') teamId!: string; + /** loaded_in_global_threads : Flag to differentiate the unread threads loaded for showing unread counts/mentions */ + @field('loaded_in_global_threads') loadedInGlobalThreads!: boolean; + @immutableRelation(THREAD, 'thread_id') thread!: Relation; @immutableRelation(TEAM, 'team_id') team!: Relation; diff --git a/app/database/operator/server_data_operator/handlers/thread.test.ts b/app/database/operator/server_data_operator/handlers/thread.test.ts index 28ac4976fb..6ea62e7a2b 100644 --- a/app/database/operator/server_data_operator/handlers/thread.test.ts +++ b/app/database/operator/server_data_operator/handlers/thread.test.ts @@ -47,6 +47,7 @@ describe('*** Operator: Thread Handlers tests ***', () => { is_following: true, unread_replies: 0, unread_mentions: 0, + loaded_in_global_threads: false, }, ] as Thread[]; @@ -126,6 +127,7 @@ describe('*** Operator: Thread Handlers tests ***', () => { is_following: true, unread_replies: 0, unread_mentions: 0, + loaded_in_global_threads: true, }, { id: 'thread-2', @@ -138,6 +140,7 @@ describe('*** Operator: Thread Handlers tests ***', () => { is_following: true, unread_replies: 0, unread_mentions: 0, + loaded_in_global_threads: true, }, ] as Thread[]; @@ -151,8 +154,9 @@ describe('*** Operator: Thread Handlers tests ***', () => { id: 'user-1', }], is_following: true, - unread_replies: 0, + unread_replies: 2, unread_mentions: 0, + loaded_in_global_threads: false, }, ] as Thread[]; @@ -165,12 +169,16 @@ describe('*** Operator: Thread Handlers tests ***', () => { expect(spyOnPrepareRecords).toHaveBeenCalledWith({ createRaws: [{ - raw: {team_id: 'team_id_1', thread_id: 'thread-2'}, + raw: {team_id: 'team_id_1', thread_id: 'thread-2', loaded_in_global_threads: true}, }, { - raw: {team_id: 'team_id_2', thread_id: 'thread-2'}, + raw: {team_id: 'team_id_2', thread_id: 'thread-2', loaded_in_global_threads: false}, }], transformer: transformThreadInTeamRecord, - updateRaws: [], + updateRaws: [ + expect.objectContaining({ + raw: {team_id: 'team_id_1', thread_id: 'thread-1', loaded_in_global_threads: true}, + }), + ], tableName: 'ThreadsInTeam', }); }); diff --git a/app/database/operator/server_data_operator/handlers/thread_in_team.ts b/app/database/operator/server_data_operator/handlers/thread_in_team.ts index 0c07858fd3..590f7f8389 100644 --- a/app/database/operator/server_data_operator/handlers/thread_in_team.ts +++ b/app/database/operator/server_data_operator/handlers/thread_in_team.ts @@ -5,9 +5,9 @@ import {Q, Database} from '@nozbe/watermelondb'; import {MM_TABLES} from '@constants/database'; import {transformThreadInTeamRecord} from '@database/operator/server_data_operator/transformers/thread'; -import {getRawRecordPairs} from '@database/operator/utils/general'; +import {getRawRecordPairs, getValidRecordsForUpdate} from '@database/operator/utils/general'; -import type {HandleThreadInTeamArgs} from '@typings/database/database'; +import type {HandleThreadInTeamArgs, RecordPair} from '@typings/database/database'; import type ThreadInTeamModel from '@typings/database/models/servers/thread_in_team'; export interface ThreadInTeamHandlerMix { @@ -22,6 +22,7 @@ const ThreadInTeamHandler = (superclass: any) => class extends superclass { return []; } + const update: RecordPair[] = []; const create: ThreadInTeam[] = []; const teamIds = Object.keys(threadsMap); for await (const teamId of teamIds) { @@ -30,23 +31,33 @@ const ThreadInTeamHandler = (superclass: any) => class extends superclass { ).fetch(); for (const thread of threadsMap[teamId]) { - const exists = chunks.some((threadInTeam) => { + const chunk = chunks.find((threadInTeam) => { return threadInTeam.threadId === thread.id; }); - if (!exists) { + const newValue = { + thread_id: thread.id, + team_id: teamId, + loaded_in_global_threads: thread.loaded_in_global_threads, + }; + + // update record if loaded_in_global_threads is true + if (chunk && thread.loaded_in_global_threads) { + update.push(getValidRecordsForUpdate({ + tableName: THREADS_IN_TEAM, + newValue, + existingRecord: chunk, + })); + } else { // create chunk - create.push({ - thread_id: thread.id, - team_id: teamId, - }); + create.push(newValue); } } } const threadsInTeam = (await this.prepareRecords({ createRaws: getRawRecordPairs(create), - updateRaws: [], + updateRaws: update, transformer: transformThreadInTeamRecord, tableName: THREADS_IN_TEAM, })) as ThreadInTeamModel[]; diff --git a/app/database/operator/server_data_operator/transformers/thread.ts b/app/database/operator/server_data_operator/transformers/thread.ts index c42f3ea637..44dd6e010d 100644 --- a/app/database/operator/server_data_operator/transformers/thread.ts +++ b/app/database/operator/server_data_operator/transformers/thread.ts @@ -37,7 +37,6 @@ export const transformThreadRecord = ({action, database, value}: TransformerArgs thread.isFollowing = raw.is_following ?? record?.isFollowing; thread.unreadReplies = raw.unread_replies; thread.unreadMentions = raw.unread_mentions; - thread.loadedInGlobalThreads = raw.loaded_in_global_threads || record?.loadedInGlobalThreads; }; return prepareBaseRecord({ @@ -76,10 +75,14 @@ export const transformThreadParticipantRecord = ({action, database, value}: Tran export const transformThreadInTeamRecord = ({action, database, value}: TransformerArgs): Promise => { const raw = value.raw as ThreadInTeam; + const record = value.record as ThreadInTeamModel; const fieldsMapper = (threadInTeam: ThreadInTeamModel) => { threadInTeam.threadId = raw.thread_id; threadInTeam.teamId = raw.team_id; + + // if it's already loaded don't change it + threadInTeam.loadedInGlobalThreads = record?.loadedInGlobalThreads || raw.loaded_in_global_threads; }; return prepareBaseRecord({ diff --git a/app/database/schema/server/table_schemas/thread.ts b/app/database/schema/server/table_schemas/thread.ts index b7fdcb1ac2..87c93f2b78 100644 --- a/app/database/schema/server/table_schemas/thread.ts +++ b/app/database/schema/server/table_schemas/thread.ts @@ -16,6 +16,5 @@ export default tableSchema({ {name: 'reply_count', type: 'number'}, {name: 'unread_replies', type: 'number'}, {name: 'unread_mentions', type: 'number'}, - {name: 'loaded_in_global_threads', type: 'boolean'}, ], }); diff --git a/app/database/schema/server/table_schemas/thread_in_team.ts b/app/database/schema/server/table_schemas/thread_in_team.ts index aa0fb3d806..f93c418309 100644 --- a/app/database/schema/server/table_schemas/thread_in_team.ts +++ b/app/database/schema/server/table_schemas/thread_in_team.ts @@ -12,5 +12,6 @@ export default tableSchema({ columns: [ {name: 'team_id', type: 'string', isIndexed: true}, {name: 'thread_id', type: 'string', isIndexed: true}, + {name: 'loaded_in_global_threads', type: 'boolean', isIndexed: true}, ], }); diff --git a/app/database/schema/server/test.ts b/app/database/schema/server/test.ts index 673bff2e40..5a56fb5fca 100644 --- a/app/database/schema/server/test.ts +++ b/app/database/schema/server/test.ts @@ -472,7 +472,6 @@ describe('*** Test schema for SERVER database ***', () => { reply_count: {name: 'reply_count', type: 'number'}, unread_replies: {name: 'unread_replies', type: 'number'}, unread_mentions: {name: 'unread_mentions', type: 'number'}, - loaded_in_global_threads: {name: 'loaded_in_global_threads', type: 'boolean'}, }, columnArray: [ {name: 'last_reply_at', type: 'number'}, @@ -481,7 +480,6 @@ describe('*** Test schema for SERVER database ***', () => { {name: 'reply_count', type: 'number'}, {name: 'unread_replies', type: 'number'}, {name: 'unread_mentions', type: 'number'}, - {name: 'loaded_in_global_threads', type: 'boolean'}, ], }, [THREAD_PARTICIPANT]: { @@ -502,10 +500,12 @@ describe('*** Test schema for SERVER database ***', () => { columns: { team_id: {name: 'team_id', type: 'string', isIndexed: true}, thread_id: {name: 'thread_id', type: 'string', isIndexed: true}, + loaded_in_global_threads: {name: 'loaded_in_global_threads', type: 'boolean', isIndexed: true}, }, columnArray: [ {name: 'team_id', type: 'string', isIndexed: true}, {name: 'thread_id', type: 'string', isIndexed: true}, + {name: 'loaded_in_global_threads', type: 'boolean', isIndexed: true}, ], }, [USER]: { diff --git a/types/database/models/servers/thread.d.ts b/types/database/models/servers/thread.d.ts index a3612bfd26..02f399736d 100644 --- a/types/database/models/servers/thread.d.ts +++ b/types/database/models/servers/thread.d.ts @@ -35,9 +35,6 @@ export default class ThreadModel extends Model { /** unread_mentions : The number of mentions that are not read by the user. */ unreadMentions: number; - /** loaded_in_global_threads : Flag to differentiate the unread threads loaded for showing unread counts/mentions */ - loadedInGlobalThreads: boolean; - /** participants: All the participants of the thread */ participants: Query; diff --git a/types/database/models/servers/thread_in_team.d.ts b/types/database/models/servers/thread_in_team.d.ts index 9e35033a76..ce384d9bab 100644 --- a/types/database/models/servers/thread_in_team.d.ts +++ b/types/database/models/servers/thread_in_team.d.ts @@ -25,6 +25,9 @@ export default class ThreadInTeamModel extends Model { /** teamId: Associated thread identifier */ teamId: string; + /** loaded_in_global_threads : Flag to differentiate the unread threads loaded for showing unread counts/mentions */ + loadedInGlobalThreads: boolean; + /** thread : The related record to the parent Thread model */ thread: Relation; diff --git a/types/database/raw_values.d.ts b/types/database/raw_values.d.ts index 703ca78726..af70143593 100644 --- a/types/database/raw_values.d.ts +++ b/types/database/raw_values.d.ts @@ -85,6 +85,7 @@ type TermsOfService = { type ThreadInTeam = { thread_id: string; team_id: string; + loaded_in_global_threads: boolean; }; type RawValue =