forked from Ivasoft/mattermost-mobile
[Gekidou] db manager database getters (#6377)
This commit is contained in:
@@ -5,40 +5,37 @@ import {GLOBAL_IDENTIFIERS} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
|
||||
export const storeDeviceToken = async (token: string, prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.appDatabase?.operator;
|
||||
|
||||
if (!operator) {
|
||||
return {error: 'No App database found'};
|
||||
try {
|
||||
const {operator} = DatabaseManager.getAppDatabaseAndOperator();
|
||||
return operator.handleGlobal({
|
||||
globals: [{id: GLOBAL_IDENTIFIERS.DEVICE_TOKEN, value: token}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
return operator.handleGlobal({
|
||||
globals: [{id: GLOBAL_IDENTIFIERS.DEVICE_TOKEN, value: token}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
};
|
||||
|
||||
export const storeMultiServerTutorial = async (prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.appDatabase?.operator;
|
||||
|
||||
if (!operator) {
|
||||
return {error: 'No App database found'};
|
||||
try {
|
||||
const {operator} = DatabaseManager.getAppDatabaseAndOperator();
|
||||
return operator.handleGlobal({
|
||||
globals: [{id: GLOBAL_IDENTIFIERS.MULTI_SERVER_TUTORIAL, value: 'true'}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
return operator.handleGlobal({
|
||||
globals: [{id: GLOBAL_IDENTIFIERS.MULTI_SERVER_TUTORIAL, value: 'true'}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
};
|
||||
|
||||
export const storeProfileLongPressTutorial = async (prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.appDatabase?.operator;
|
||||
|
||||
if (!operator) {
|
||||
return {error: 'No App database found'};
|
||||
try {
|
||||
const {operator} = DatabaseManager.getAppDatabaseAndOperator();
|
||||
return operator.handleGlobal({
|
||||
globals: [{id: GLOBAL_IDENTIFIERS.PROFILE_LONG_PRESS_TUTORIAL, value: 'true'}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
return operator.handleGlobal({
|
||||
globals: [{id: GLOBAL_IDENTIFIERS.PROFILE_LONG_PRESS_TUTORIAL, value: 'true'}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -14,12 +14,8 @@ import {pluckUnique} from '@utils/helpers';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
|
||||
export const deleteCategory = async (serverUrl: string, categoryId: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const category = await getCategoryById(database, categoryId);
|
||||
|
||||
if (category) {
|
||||
@@ -37,67 +33,59 @@ export const deleteCategory = async (serverUrl: string, categoryId: string) => {
|
||||
};
|
||||
|
||||
export async function storeCategories(serverUrl: string, categories: CategoryWithChannels[], prune = false, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const modelPromises: Array<Promise<Model[]>> = [];
|
||||
const preparedCategories = prepareCategories(operator, categories);
|
||||
if (preparedCategories) {
|
||||
modelPromises.push(preparedCategories);
|
||||
}
|
||||
|
||||
const preparedCategoryChannels = prepareCategoryChannels(operator, categories);
|
||||
if (preparedCategoryChannels) {
|
||||
modelPromises.push(preparedCategoryChannels);
|
||||
}
|
||||
|
||||
const models = await Promise.all(modelPromises);
|
||||
const flattenedModels = models.flat();
|
||||
|
||||
if (prune && categories.length) {
|
||||
const {database} = operator;
|
||||
const remoteCategoryIds = new Set(categories.map((cat) => cat.id));
|
||||
|
||||
// If the passed categories have more than one team, we want to update across teams
|
||||
const teamIds = pluckUnique('team_id')(categories) as string[];
|
||||
const localCategories = await queryCategoriesByTeamIds(database, teamIds).fetch();
|
||||
|
||||
localCategories.
|
||||
filter((category) => category.type === 'custom').
|
||||
forEach((localCategory) => {
|
||||
if (!remoteCategoryIds.has(localCategory.id)) {
|
||||
localCategory.prepareDestroyPermanently();
|
||||
flattenedModels.push(localCategory);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (prepareRecordsOnly) {
|
||||
return {models: flattenedModels};
|
||||
}
|
||||
|
||||
if (flattenedModels?.length > 0) {
|
||||
try {
|
||||
await operator.batchRecords(flattenedModels);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH CATEGORIES', error);
|
||||
return {error};
|
||||
const modelPromises: Array<Promise<Model[]>> = [];
|
||||
const preparedCategories = prepareCategories(operator, categories);
|
||||
if (preparedCategories) {
|
||||
modelPromises.push(preparedCategories);
|
||||
}
|
||||
}
|
||||
|
||||
return {models: flattenedModels};
|
||||
const preparedCategoryChannels = prepareCategoryChannels(operator, categories);
|
||||
if (preparedCategoryChannels) {
|
||||
modelPromises.push(preparedCategoryChannels);
|
||||
}
|
||||
|
||||
const models = await Promise.all(modelPromises);
|
||||
const flattenedModels = models.flat();
|
||||
|
||||
if (prune && categories.length) {
|
||||
const remoteCategoryIds = new Set(categories.map((cat) => cat.id));
|
||||
|
||||
// If the passed categories have more than one team, we want to update across teams
|
||||
const teamIds = pluckUnique('team_id')(categories) as string[];
|
||||
const localCategories = await queryCategoriesByTeamIds(database, teamIds).fetch();
|
||||
|
||||
localCategories.
|
||||
filter((category) => category.type === 'custom').
|
||||
forEach((localCategory) => {
|
||||
if (!remoteCategoryIds.has(localCategory.id)) {
|
||||
localCategory.prepareDestroyPermanently();
|
||||
flattenedModels.push(localCategory);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (prepareRecordsOnly) {
|
||||
return {models: flattenedModels};
|
||||
}
|
||||
|
||||
if (flattenedModels?.length > 0) {
|
||||
await operator.batchRecords(flattenedModels);
|
||||
}
|
||||
|
||||
return {models: flattenedModels};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO STORE CATEGORIES', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const toggleCollapseCategory = async (serverUrl: string, categoryId: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl].database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const category = await getCategoryById(database, categoryId);
|
||||
|
||||
if (category) {
|
||||
@@ -117,47 +105,46 @@ export const toggleCollapseCategory = async (serverUrl: string, categoryId: stri
|
||||
};
|
||||
|
||||
export async function addChannelToDefaultCategory(serverUrl: string, channel: Channel | ChannelModel, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const teamId = 'teamId' in channel ? channel.teamId : channel.team_id;
|
||||
const userId = await getCurrentUserId(database);
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const teamId = 'teamId' in channel ? channel.teamId : channel.team_id;
|
||||
const userId = await getCurrentUserId(database);
|
||||
if (!userId) {
|
||||
return {error: 'no current user id'};
|
||||
}
|
||||
|
||||
const models: Model[] = [];
|
||||
const categoriesWithChannels: CategoryWithChannels[] = [];
|
||||
|
||||
if (isDMorGM(channel)) {
|
||||
const allTeamIds = await queryMyTeams(database).fetchIds();
|
||||
const categories = await queryCategoriesByTeamIds(database, allTeamIds).fetch();
|
||||
const channelCategories = categories.filter((c) => c.type === DMS_CATEGORY);
|
||||
for await (const cc of channelCategories) {
|
||||
const cwc = await cc.toCategoryWithChannels();
|
||||
cwc.channel_ids.unshift(channel.id);
|
||||
categoriesWithChannels.push(cwc);
|
||||
}
|
||||
} else {
|
||||
const categories = await queryCategoriesByTeamIds(database, [teamId]).fetch();
|
||||
const channelCategory = categories.find((c) => c.type === CHANNELS_CATEGORY);
|
||||
if (channelCategory) {
|
||||
const cwc = await channelCategory.toCategoryWithChannels();
|
||||
cwc.channel_ids.unshift(channel.id);
|
||||
categoriesWithChannels.push(cwc);
|
||||
if (!userId) {
|
||||
return {error: 'no current user id'};
|
||||
}
|
||||
|
||||
const ccModels = await prepareCategoryChannels(operator, categoriesWithChannels);
|
||||
models.push(...ccModels);
|
||||
}
|
||||
const models: Model[] = [];
|
||||
const categoriesWithChannels: CategoryWithChannels[] = [];
|
||||
|
||||
if (models.length && !prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
if (isDMorGM(channel)) {
|
||||
const allTeamIds = await queryMyTeams(database).fetchIds();
|
||||
const categories = await queryCategoriesByTeamIds(database, allTeamIds).fetch();
|
||||
const channelCategories = categories.filter((c) => c.type === DMS_CATEGORY);
|
||||
for await (const cc of channelCategories) {
|
||||
const cwc = await cc.toCategoryWithChannels();
|
||||
cwc.channel_ids.unshift(channel.id);
|
||||
categoriesWithChannels.push(cwc);
|
||||
}
|
||||
} else {
|
||||
const categories = await queryCategoriesByTeamIds(database, [teamId]).fetch();
|
||||
const channelCategory = categories.find((c) => c.type === CHANNELS_CATEGORY);
|
||||
if (channelCategory) {
|
||||
const cwc = await channelCategory.toCategoryWithChannels();
|
||||
cwc.channel_ids.unshift(channel.id);
|
||||
categoriesWithChannels.push(cwc);
|
||||
}
|
||||
|
||||
return {models};
|
||||
const ccModels = await prepareCategoryChannels(operator, categoriesWithChannels);
|
||||
models.push(...ccModels);
|
||||
}
|
||||
|
||||
if (models.length && !prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
|
||||
return {models};
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,9 @@ import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
export async function switchToChannel(serverUrl: string, channelId: string, teamId?: string, skipLastUnread = false, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
let models: Model[] = [];
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
let models: Model[] = [];
|
||||
const dt = Date.now();
|
||||
const isTabletDevice = await isTablet();
|
||||
const system = await getCommonSystemValues(database);
|
||||
@@ -113,103 +108,89 @@ export async function switchToChannel(serverUrl: string, channelId: string, team
|
||||
console.log('channel switch to', channel?.displayName, channelId, (Date.now() - dt), 'ms'); //eslint-disable-line
|
||||
}
|
||||
}
|
||||
|
||||
return {models};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed to switch to channelId', channelId, 'teamId', teamId, 'error', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {models};
|
||||
}
|
||||
|
||||
export async function removeCurrentUserFromChannel(serverUrl: string, channelId: string, prepareRecordsOnly = false) {
|
||||
const serverDatabase = DatabaseManager.serverDatabases[serverUrl];
|
||||
if (!serverDatabase) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const {operator, database} = serverDatabase;
|
||||
const models: Model[] = [];
|
||||
const myChannel = await getMyChannel(database, channelId);
|
||||
if (myChannel) {
|
||||
const channel = await myChannel.channel.fetch();
|
||||
if (!channel) {
|
||||
throw new Error('myChannel present but no channel on the database');
|
||||
}
|
||||
models.push(...await prepareDeleteChannel(channel));
|
||||
let teamId = channel.teamId;
|
||||
if (teamId) {
|
||||
teamId = await getCurrentTeamId(database);
|
||||
}
|
||||
|
||||
const models: Model[] = [];
|
||||
const myChannel = await getMyChannel(database, channelId);
|
||||
if (myChannel) {
|
||||
const channel = await myChannel.channel.fetch();
|
||||
if (!channel) {
|
||||
return {error: 'myChannel present but no channel on the database'};
|
||||
}
|
||||
models.push(...await prepareDeleteChannel(channel));
|
||||
let teamId = channel.teamId;
|
||||
if (teamId) {
|
||||
teamId = await getCurrentTeamId(database);
|
||||
}
|
||||
// We update the history ASAP to avoid clashes with channel switch.
|
||||
await removeChannelFromTeamHistory(operator, teamId, channel.id, false);
|
||||
|
||||
// We update the history ASAP to avoid clashes with channel switch.
|
||||
await removeChannelFromTeamHistory(operator, teamId, channel.id, false);
|
||||
|
||||
if (models.length && !prepareRecordsOnly) {
|
||||
try {
|
||||
if (models.length && !prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
} catch {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH CHANGES FOR REMOVE USER FROM CHANNEL');
|
||||
}
|
||||
}
|
||||
return {models};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('failed to removeCurrentUserFromChannel', error);
|
||||
return {error};
|
||||
}
|
||||
return {models};
|
||||
}
|
||||
|
||||
export async function setChannelDeleteAt(serverUrl: string, channelId: string, deleteAt: number) {
|
||||
const serverDatabase = DatabaseManager.serverDatabases[serverUrl];
|
||||
if (!serverDatabase) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {operator, database} = serverDatabase;
|
||||
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = channel.prepareUpdate((c) => {
|
||||
c.deleteAt = deleteAt;
|
||||
});
|
||||
|
||||
try {
|
||||
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = channel.prepareUpdate((c) => {
|
||||
c.deleteAt = deleteAt;
|
||||
});
|
||||
await operator.batchRecords([model]);
|
||||
} catch {
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH CHANGES FOR CHANNEL DELETE AT');
|
||||
console.log('FAILED TO BATCH CHANGES FOR CHANNEL DELETE AT', error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function selectAllMyChannelIds(serverUrl: string) {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
return queryAllMyChannel(database).fetchIds();
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
return queryAllMyChannel(database).fetchIds();
|
||||
}
|
||||
|
||||
export async function markChannelAsViewed(serverUrl: string, channelId: string, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const member = await getMyChannel(operator.database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
|
||||
member.prepareUpdate((m) => {
|
||||
m.isUnread = false;
|
||||
m.mentionsCount = 0;
|
||||
m.manuallyUnread = false;
|
||||
m.viewedAt = member.lastViewedAt;
|
||||
m.lastViewedAt = Date.now();
|
||||
});
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const member = await getMyChannel(database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
|
||||
member.prepareUpdate((m) => {
|
||||
m.isUnread = false;
|
||||
m.mentionsCount = 0;
|
||||
m.manuallyUnread = false;
|
||||
m.viewedAt = member.lastViewedAt;
|
||||
m.lastViewedAt = Date.now();
|
||||
});
|
||||
PushNotifications.cancelChannelNotifications(channelId);
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([member]);
|
||||
@@ -217,53 +198,47 @@ export async function markChannelAsViewed(serverUrl: string, channelId: string,
|
||||
|
||||
return {member};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed markChannelAsViewed', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function markChannelAsUnread(serverUrl: string, channelId: string, messageCount: number, mentionsCount: number, lastViewed: number, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const member = await getMyChannel(operator.database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
|
||||
member.prepareUpdate((m) => {
|
||||
m.viewedAt = lastViewed - 1;
|
||||
m.lastViewedAt = lastViewed - 1;
|
||||
m.messageCount = messageCount;
|
||||
m.mentionsCount = mentionsCount;
|
||||
m.manuallyUnread = true;
|
||||
m.isUnread = true;
|
||||
});
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const member = await getMyChannel(database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
|
||||
member.prepareUpdate((m) => {
|
||||
m.viewedAt = lastViewed - 1;
|
||||
m.lastViewedAt = lastViewed - 1;
|
||||
m.messageCount = messageCount;
|
||||
m.mentionsCount = mentionsCount;
|
||||
m.manuallyUnread = true;
|
||||
m.isUnread = true;
|
||||
});
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([member]);
|
||||
}
|
||||
|
||||
return {member};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed markChannelAsUnread', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function resetMessageCount(serverUrl: string, channelId: string) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const member = await getMyChannel(operator.database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const member = await getMyChannel(database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
member.prepareUpdate((m) => {
|
||||
m.messageCount = 0;
|
||||
});
|
||||
@@ -271,185 +246,185 @@ export async function resetMessageCount(serverUrl: string, channelId: string) {
|
||||
|
||||
return member;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed resetMessageCount', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function storeMyChannelsForTeam(serverUrl: string, teamId: string, channels: Channel[], memberships: ChannelMembership[], prepareRecordsOnly = false, isCRTEnabled?: boolean) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const modelPromises: Array<Promise<Model[]>> = [
|
||||
...await prepareMyChannelsForTeam(operator, teamId, channels, memberships, isCRTEnabled),
|
||||
];
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const modelPromises: Array<Promise<Model[]>> = [
|
||||
...await prepareMyChannelsForTeam(operator, teamId, channels, memberships, isCRTEnabled),
|
||||
];
|
||||
|
||||
const models = await Promise.all(modelPromises);
|
||||
if (!models.length) {
|
||||
return {models: []};
|
||||
}
|
||||
|
||||
const flattenedModels = models.flat();
|
||||
|
||||
if (prepareRecordsOnly) {
|
||||
return {models: flattenedModels};
|
||||
}
|
||||
|
||||
if (flattenedModels.length) {
|
||||
try {
|
||||
await operator.batchRecords(flattenedModels);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH CHANNELS');
|
||||
return {error};
|
||||
const models = await Promise.all(modelPromises);
|
||||
if (!models.length) {
|
||||
return {models: []};
|
||||
}
|
||||
}
|
||||
|
||||
return {models: flattenedModels};
|
||||
const flattenedModels = models.flat();
|
||||
|
||||
if (prepareRecordsOnly) {
|
||||
return {models: flattenedModels};
|
||||
}
|
||||
|
||||
if (flattenedModels.length) {
|
||||
await operator.batchRecords(flattenedModels);
|
||||
}
|
||||
|
||||
return {models: flattenedModels};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed storeMyChannelsForTeam', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateMyChannelFromWebsocket(serverUrl: string, channelMember: ChannelMembership, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const member = await getMyChannel(operator.database, channelMember.channel_id);
|
||||
if (member) {
|
||||
member.prepareUpdate((m) => {
|
||||
m.roles = channelMember.roles;
|
||||
});
|
||||
if (!prepareRecordsOnly) {
|
||||
operator.batchRecords([member]);
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const member = await getMyChannel(database, channelMember.channel_id);
|
||||
if (member) {
|
||||
member.prepareUpdate((m) => {
|
||||
m.roles = channelMember.roles;
|
||||
});
|
||||
if (!prepareRecordsOnly) {
|
||||
operator.batchRecords([member]);
|
||||
}
|
||||
}
|
||||
return {model: member};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateMyChannelFromWebsocket', error);
|
||||
return {error};
|
||||
}
|
||||
return {model: member};
|
||||
}
|
||||
|
||||
export async function updateChannelInfoFromChannel(serverUrl: string, channel: Channel, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const newInfo = await operator.handleChannelInfo({channelInfos: [{
|
||||
header: channel.header,
|
||||
purpose: channel.purpose,
|
||||
id: channel.id,
|
||||
}],
|
||||
prepareRecordsOnly: true});
|
||||
if (!prepareRecordsOnly) {
|
||||
operator.batchRecords(newInfo);
|
||||
}
|
||||
return {model: newInfo};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateChannelInfoFromChannel', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
const newInfo = await operator.handleChannelInfo({channelInfos: [{
|
||||
header: channel.header,
|
||||
purpose: channel.purpose,
|
||||
id: channel.id,
|
||||
}],
|
||||
prepareRecordsOnly: true});
|
||||
if (!prepareRecordsOnly) {
|
||||
operator.batchRecords(newInfo);
|
||||
}
|
||||
return {model: newInfo};
|
||||
}
|
||||
|
||||
export async function updateLastPostAt(serverUrl: string, channelId: string, lastPostAt: number, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const member = await getMyChannel(database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
|
||||
const member = await getMyChannel(operator.database, channelId);
|
||||
if (!member) {
|
||||
return {error: 'not a member'};
|
||||
}
|
||||
if (lastPostAt > member.lastPostAt) {
|
||||
member.prepareUpdate((m) => {
|
||||
m.lastPostAt = lastPostAt;
|
||||
});
|
||||
|
||||
if (lastPostAt > member.lastPostAt) {
|
||||
member.prepareUpdate((m) => {
|
||||
m.lastPostAt = lastPostAt;
|
||||
});
|
||||
|
||||
try {
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([member]);
|
||||
}
|
||||
} catch (error) {
|
||||
return {error};
|
||||
|
||||
return {member};
|
||||
}
|
||||
|
||||
return {member};
|
||||
return {member: undefined};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateLastPostAt', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {member: undefined};
|
||||
}
|
||||
|
||||
type User = UserProfile | UserModel;
|
||||
export async function updateChannelsDisplayName(serverUrl: string, channels: ChannelModel[], users: User[], prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {};
|
||||
}
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const currentUser = await getCurrentUser(database);
|
||||
if (!currentUser) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
const currentUser = await getCurrentUser(database);
|
||||
if (!currentUser) {
|
||||
return {};
|
||||
}
|
||||
const {config, license} = await getCommonSystemValues(database);
|
||||
const preferences = await queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT).fetch();
|
||||
const displaySettings = getTeammateNameDisplaySetting(preferences, config, license);
|
||||
const models: Model[] = [];
|
||||
for await (const channel of channels) {
|
||||
let newDisplayName = '';
|
||||
if (channel.type === General.DM_CHANNEL) {
|
||||
const otherUserId = getUserIdFromChannelName(currentUser.id, channel.name);
|
||||
const user = users.find((u) => u.id === otherUserId);
|
||||
newDisplayName = displayUsername(user, currentUser.locale, displaySettings, false);
|
||||
} else {
|
||||
const dbProfiles = await queryUsersOnChannel(database, channel.id).fetch();
|
||||
const profileIds = new Set(dbProfiles.map((p) => p.id));
|
||||
const gmUsers = users.filter((u) => profileIds.has(u.id));
|
||||
if (gmUsers.length) {
|
||||
const uIds = new Set(gmUsers.map((u) => u.id));
|
||||
const newProfiles: Array<UserModel|UserProfile> = dbProfiles.filter((u) => !uIds.has(u.id));
|
||||
newProfiles.push(...gmUsers);
|
||||
newDisplayName = displayGroupMessageName(newProfiles, currentUser.locale, displaySettings, currentUser.id);
|
||||
}
|
||||
}
|
||||
|
||||
const {config, license} = await getCommonSystemValues(database);
|
||||
const preferences = await queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT).fetch();
|
||||
const displaySettings = getTeammateNameDisplaySetting(preferences, config, license);
|
||||
const models: Model[] = [];
|
||||
for await (const channel of channels) {
|
||||
let newDisplayName = '';
|
||||
if (channel.type === General.DM_CHANNEL) {
|
||||
const otherUserId = getUserIdFromChannelName(currentUser.id, channel.name);
|
||||
const user = users.find((u) => u.id === otherUserId);
|
||||
newDisplayName = displayUsername(user, currentUser.locale, displaySettings, false);
|
||||
} else {
|
||||
const dbProfiles = await queryUsersOnChannel(database, channel.id).fetch();
|
||||
const profileIds = new Set(dbProfiles.map((p) => p.id));
|
||||
const gmUsers = users.filter((u) => profileIds.has(u.id));
|
||||
if (gmUsers.length) {
|
||||
const uIds = new Set(gmUsers.map((u) => u.id));
|
||||
const newProfiles: Array<UserModel|UserProfile> = dbProfiles.filter((u) => !uIds.has(u.id));
|
||||
newProfiles.push(...gmUsers);
|
||||
newDisplayName = displayGroupMessageName(newProfiles, currentUser.locale, displaySettings, currentUser.id);
|
||||
if (newDisplayName && channel.displayName !== newDisplayName) {
|
||||
channel.prepareUpdate((c) => {
|
||||
c.displayName = extractChannelDisplayName({
|
||||
type: c.type,
|
||||
display_name: newDisplayName,
|
||||
fake: true,
|
||||
}, c);
|
||||
});
|
||||
models.push(channel);
|
||||
}
|
||||
}
|
||||
|
||||
if (newDisplayName && channel.displayName !== newDisplayName) {
|
||||
channel.prepareUpdate((c) => {
|
||||
c.displayName = extractChannelDisplayName({
|
||||
type: c.type,
|
||||
display_name: newDisplayName,
|
||||
fake: true,
|
||||
}, c);
|
||||
});
|
||||
models.push(channel);
|
||||
if (models.length && !prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
}
|
||||
|
||||
if (models.length && !prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
return {models};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateChannelsDisplayName', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {models};
|
||||
}
|
||||
|
||||
export async function showUnreadChannelsOnly(serverUrl: string, onlyUnreads: boolean) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
return operator.handleSystem({
|
||||
systems: [{
|
||||
id: SYSTEM_IDENTIFIERS.ONLY_UNREADS,
|
||||
value: JSON.stringify(onlyUnreads),
|
||||
}],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed showUnreadChannelsOnly', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return operator.handleSystem({
|
||||
systems: [{
|
||||
id: SYSTEM_IDENTIFIERS.ONLY_UNREADS,
|
||||
value: JSON.stringify(onlyUnreads),
|
||||
}],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
}
|
||||
|
||||
export const updateDmGmDisplayName = async (serverUrl: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
if (!currentUserId) {
|
||||
return {error: 'The current user id could not be retrieved from the database'};
|
||||
@@ -471,6 +446,8 @@ export const updateDmGmDisplayName = async (serverUrl: string) => {
|
||||
|
||||
return {channels};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateDmGmDisplayName', error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,163 +5,157 @@ import DatabaseManager from '@database/manager';
|
||||
import {getDraft} from '@queries/servers/drafts';
|
||||
|
||||
export async function updateDraftFile(serverUrl: string, channelId: string, rootId: string, file: FileInfo, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const draft = await getDraft(operator.database, channelId, rootId);
|
||||
if (!draft) {
|
||||
return {error: 'no draft'};
|
||||
}
|
||||
|
||||
const i = draft.files.findIndex((v) => v.clientId === file.clientId);
|
||||
if (i === -1) {
|
||||
return {error: 'file not found'};
|
||||
}
|
||||
|
||||
// We create a new list to make sure we re-render the draft input.
|
||||
const newFiles = [...draft.files];
|
||||
newFiles[i] = file;
|
||||
draft.prepareUpdate((d) => {
|
||||
d.files = newFiles;
|
||||
});
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const draft = await getDraft(database, channelId, rootId);
|
||||
if (!draft) {
|
||||
return {error: 'no draft'};
|
||||
}
|
||||
|
||||
const i = draft.files.findIndex((v) => v.clientId === file.clientId);
|
||||
if (i === -1) {
|
||||
return {error: 'file not found'};
|
||||
}
|
||||
|
||||
// We create a new list to make sure we re-render the draft input.
|
||||
const newFiles = [...draft.files];
|
||||
newFiles[i] = file;
|
||||
draft.prepareUpdate((d) => {
|
||||
d.files = newFiles;
|
||||
});
|
||||
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([draft]);
|
||||
}
|
||||
|
||||
return {draft};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateDraftFile', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function removeDraftFile(serverUrl: string, channelId: string, rootId: string, clientId: string, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const draft = await getDraft(operator.database, channelId, rootId);
|
||||
if (!draft) {
|
||||
return {error: 'no draft'};
|
||||
}
|
||||
|
||||
const i = draft.files.findIndex((v) => v.clientId === clientId);
|
||||
if (i === -1) {
|
||||
return {error: 'file not found'};
|
||||
}
|
||||
|
||||
if (draft.files.length === 1 && !draft.message) {
|
||||
draft.prepareDestroyPermanently();
|
||||
} else {
|
||||
draft.prepareUpdate((d) => {
|
||||
d.files = draft.files.filter((v, index) => index !== i);
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const draft = await getDraft(database, channelId, rootId);
|
||||
if (!draft) {
|
||||
return {error: 'no draft'};
|
||||
}
|
||||
|
||||
const i = draft.files.findIndex((v) => v.clientId === clientId);
|
||||
if (i === -1) {
|
||||
return {error: 'file not found'};
|
||||
}
|
||||
|
||||
if (draft.files.length === 1 && !draft.message) {
|
||||
draft.prepareDestroyPermanently();
|
||||
} else {
|
||||
draft.prepareUpdate((d) => {
|
||||
d.files = draft.files.filter((v, index) => index !== i);
|
||||
});
|
||||
}
|
||||
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([draft]);
|
||||
}
|
||||
|
||||
return {draft};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed removeDraftFile', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateDraftMessage(serverUrl: string, channelId: string, rootId: string, message: string, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const draft = await getDraft(database, channelId, rootId);
|
||||
if (!draft) {
|
||||
if (!message) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const draft = await getDraft(operator.database, channelId, rootId);
|
||||
if (!draft) {
|
||||
if (!message) {
|
||||
return {};
|
||||
const newDraft: Draft = {
|
||||
channel_id: channelId,
|
||||
root_id: rootId,
|
||||
message,
|
||||
};
|
||||
|
||||
return operator.handleDraft({drafts: [newDraft], prepareRecordsOnly});
|
||||
}
|
||||
|
||||
const newDraft: Draft = {
|
||||
channel_id: channelId,
|
||||
root_id: rootId,
|
||||
message,
|
||||
};
|
||||
if (draft.message === message) {
|
||||
return {draft};
|
||||
}
|
||||
|
||||
return operator.handleDraft({drafts: [newDraft], prepareRecordsOnly});
|
||||
}
|
||||
if (draft.files.length === 0 && !message) {
|
||||
draft.prepareDestroyPermanently();
|
||||
} else {
|
||||
draft.prepareUpdate((d) => {
|
||||
d.message = message;
|
||||
});
|
||||
}
|
||||
|
||||
if (draft.message === message) {
|
||||
return {draft};
|
||||
}
|
||||
|
||||
if (draft.files.length === 0 && !message) {
|
||||
draft.prepareDestroyPermanently();
|
||||
} else {
|
||||
draft.prepareUpdate((d) => {
|
||||
d.message = message;
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([draft]);
|
||||
}
|
||||
|
||||
return {draft};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateDraftMessage', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function addFilesToDraft(serverUrl: string, channelId: string, rootId: string, files: FileInfo[], prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const draft = await getDraft(operator.database, channelId, rootId);
|
||||
if (!draft) {
|
||||
const newDraft: Draft = {
|
||||
channel_id: channelId,
|
||||
root_id: rootId,
|
||||
files,
|
||||
message: '',
|
||||
};
|
||||
|
||||
return operator.handleDraft({drafts: [newDraft], prepareRecordsOnly});
|
||||
}
|
||||
|
||||
draft.prepareUpdate((d) => {
|
||||
d.files = [...draft.files, ...files];
|
||||
});
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const draft = await getDraft(database, channelId, rootId);
|
||||
if (!draft) {
|
||||
const newDraft: Draft = {
|
||||
channel_id: channelId,
|
||||
root_id: rootId,
|
||||
files,
|
||||
message: '',
|
||||
};
|
||||
|
||||
return operator.handleDraft({drafts: [newDraft], prepareRecordsOnly});
|
||||
}
|
||||
|
||||
draft.prepareUpdate((d) => {
|
||||
d.files = [...draft.files, ...files];
|
||||
});
|
||||
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([draft]);
|
||||
}
|
||||
|
||||
return {draft};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed addFilesToDraft', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const removeDraft = async (serverUrl: string, channelId: string, rootId = '') => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const draft = await getDraft(database, channelId, rootId);
|
||||
if (draft) {
|
||||
await database.write(async () => {
|
||||
await draft.destroyPermanently();
|
||||
});
|
||||
}
|
||||
|
||||
const draft = await getDraft(database, channelId, rootId);
|
||||
if (draft) {
|
||||
await database.write(async () => {
|
||||
await draft.destroyPermanently();
|
||||
});
|
||||
return {draft};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed removeDraft', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {draft};
|
||||
};
|
||||
|
||||
@@ -5,21 +5,19 @@ import DatabaseManager from '@database/manager';
|
||||
import {getFileById} from '@queries/servers/file';
|
||||
|
||||
export const updateLocalFile = async (serverUrl: string, file: FileInfo) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
return operator.handleFiles({files: [file], prepareRecordsOnly: false});
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateLocalFile', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return operator.handleFiles({files: [file], prepareRecordsOnly: false});
|
||||
};
|
||||
|
||||
export const updateLocalFilePath = async (serverUrl: string, fileId: string, localPath: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const file = await getFileById(database, fileId);
|
||||
if (file) {
|
||||
await database.write(async () => {
|
||||
@@ -31,6 +29,8 @@ export const updateLocalFilePath = async (serverUrl: string, fileId: string, loc
|
||||
|
||||
return {error: undefined};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateLocalFilePath', error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,14 +5,9 @@ import DatabaseManager from '@database/manager';
|
||||
import {getPostById, queryPostsInChannel, queryPostsInThread} from '@queries/servers/post';
|
||||
|
||||
export const updatePostSinceCache = async (serverUrl: string, notification: NotificationWithData) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
if (notification.payload?.channel_id) {
|
||||
const {database} = operator;
|
||||
const chunks = await queryPostsInChannel(database, notification.payload.channel_id).fetch();
|
||||
if (chunks.length) {
|
||||
const recent = chunks[0];
|
||||
@@ -28,6 +23,8 @@ export const updatePostSinceCache = async (serverUrl: string, notification: Noti
|
||||
}
|
||||
return {};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updatePostSinceCache', error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,17 +12,65 @@ import type PostModel from '@typings/database/models/servers/post';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
export const sendAddToChannelEphemeralPost = async (serverUrl: string, user: UserModel, addedUsernames: string[], messages: string[], channeId: string, postRootId = '') => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const timestamp = Date.now();
|
||||
const posts = addedUsernames.map((addedUsername, index) => {
|
||||
const message = messages[index];
|
||||
return {
|
||||
id: generateId(),
|
||||
user_id: user.id,
|
||||
channel_id: channeId,
|
||||
message,
|
||||
type: Post.POST_TYPES.EPHEMERAL_ADD_TO_CHANNEL as PostType,
|
||||
create_at: timestamp,
|
||||
edit_at: 0,
|
||||
update_at: timestamp,
|
||||
delete_at: 0,
|
||||
is_pinned: false,
|
||||
original_id: '',
|
||||
hashtags: '',
|
||||
pending_post_id: '',
|
||||
reply_count: 0,
|
||||
metadata: {},
|
||||
root_id: postRootId,
|
||||
props: {
|
||||
username: user.username,
|
||||
addedUsername,
|
||||
},
|
||||
} as Post;
|
||||
});
|
||||
|
||||
const timestamp = Date.now();
|
||||
const posts = addedUsernames.map((addedUsername, index) => {
|
||||
const message = messages[index];
|
||||
return {
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: posts.map((p) => p.id),
|
||||
posts,
|
||||
});
|
||||
|
||||
return {posts};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed sendAddToChannelEphemeralPost', error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const sendEphemeralPost = async (serverUrl: string, message: string, channeId: string, rootId = '', userId?: string) => {
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
if (!channeId) {
|
||||
throw new Error('channel Id not defined');
|
||||
}
|
||||
|
||||
let authorId = userId;
|
||||
if (!authorId) {
|
||||
authorId = await getCurrentUserId(database);
|
||||
}
|
||||
|
||||
const timestamp = Date.now();
|
||||
const post = {
|
||||
id: generateId(),
|
||||
user_id: user.id,
|
||||
user_id: authorId,
|
||||
channel_id: channeId,
|
||||
message,
|
||||
type: Post.POST_TYPES.EPHEMERAL_ADD_TO_CHANNEL as PostType,
|
||||
@@ -36,122 +84,82 @@ export const sendAddToChannelEphemeralPost = async (serverUrl: string, user: Use
|
||||
pending_post_id: '',
|
||||
reply_count: 0,
|
||||
metadata: {},
|
||||
root_id: postRootId,
|
||||
props: {
|
||||
username: user.username,
|
||||
addedUsername,
|
||||
},
|
||||
participants: null,
|
||||
root_id: rootId,
|
||||
props: {},
|
||||
} as Post;
|
||||
});
|
||||
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: posts.map((p) => p.id),
|
||||
posts,
|
||||
});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: [post.id],
|
||||
posts: [post],
|
||||
});
|
||||
|
||||
return {posts};
|
||||
};
|
||||
|
||||
export const sendEphemeralPost = async (serverUrl: string, message: string, channeId: string, rootId = '', userId?: string) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
return {post};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed sendEphemeralPost', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
if (!channeId) {
|
||||
return {error: 'channel Id not defined'};
|
||||
}
|
||||
|
||||
let authorId = userId;
|
||||
if (!authorId) {
|
||||
authorId = await getCurrentUserId(operator.database);
|
||||
}
|
||||
|
||||
const timestamp = Date.now();
|
||||
const post = {
|
||||
id: generateId(),
|
||||
user_id: authorId,
|
||||
channel_id: channeId,
|
||||
message,
|
||||
type: Post.POST_TYPES.EPHEMERAL_ADD_TO_CHANNEL as PostType,
|
||||
create_at: timestamp,
|
||||
edit_at: 0,
|
||||
update_at: timestamp,
|
||||
delete_at: 0,
|
||||
is_pinned: false,
|
||||
original_id: '',
|
||||
hashtags: '',
|
||||
pending_post_id: '',
|
||||
reply_count: 0,
|
||||
metadata: {},
|
||||
participants: null,
|
||||
root_id: rootId,
|
||||
props: {},
|
||||
} as Post;
|
||||
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: [post.id],
|
||||
posts: [post],
|
||||
});
|
||||
|
||||
return {post};
|
||||
};
|
||||
|
||||
export async function removePost(serverUrl: string, post: PostModel | Post) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
if (post.type === Post.POST_TYPES.COMBINED_USER_ACTIVITY && post.props?.system_post_ids) {
|
||||
const systemPostIds = getPostIdsForCombinedUserActivityPost(post.id);
|
||||
const removeModels = [];
|
||||
for await (const id of systemPostIds) {
|
||||
const postModel = await getPostById(database, id);
|
||||
if (postModel) {
|
||||
const preparedPost = await prepareDeletePost(postModel);
|
||||
removeModels.push(...preparedPost);
|
||||
}
|
||||
}
|
||||
|
||||
if (post.type === Post.POST_TYPES.COMBINED_USER_ACTIVITY && post.props?.system_post_ids) {
|
||||
const systemPostIds = getPostIdsForCombinedUserActivityPost(post.id);
|
||||
const removeModels = [];
|
||||
for await (const id of systemPostIds) {
|
||||
const postModel = await getPostById(operator.database, id);
|
||||
if (removeModels.length) {
|
||||
await operator.batchRecords(removeModels);
|
||||
}
|
||||
} else {
|
||||
const postModel = await getPostById(database, post.id);
|
||||
if (postModel) {
|
||||
const preparedPost = await prepareDeletePost(postModel);
|
||||
removeModels.push(...preparedPost);
|
||||
if (preparedPost.length) {
|
||||
await operator.batchRecords(preparedPost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (removeModels.length) {
|
||||
await operator.batchRecords(removeModels);
|
||||
}
|
||||
} else {
|
||||
const postModel = await getPostById(operator.database, post.id);
|
||||
if (postModel) {
|
||||
const preparedPost = await prepareDeletePost(postModel);
|
||||
if (preparedPost.length) {
|
||||
await operator.batchRecords(preparedPost);
|
||||
}
|
||||
}
|
||||
return {post};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed removePost', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {post};
|
||||
}
|
||||
|
||||
export async function markPostAsDeleted(serverUrl: string, post: Post, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const dbPost = await getPostById(database, post.id);
|
||||
if (!dbPost) {
|
||||
throw new Error('Post not found');
|
||||
}
|
||||
|
||||
const dbPost = await getPostById(operator.database, post.id);
|
||||
if (!dbPost) {
|
||||
return {error: 'Post not found'};
|
||||
}
|
||||
const model = dbPost.prepareUpdate((p) => {
|
||||
p.deleteAt = Date.now();
|
||||
p.message = '';
|
||||
p.metadata = null;
|
||||
p.props = undefined;
|
||||
});
|
||||
|
||||
const model = dbPost.prepareUpdate((p) => {
|
||||
p.deleteAt = Date.now();
|
||||
p.message = '';
|
||||
p.metadata = null;
|
||||
p.props = undefined;
|
||||
});
|
||||
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([dbPost]);
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([dbPost]);
|
||||
}
|
||||
return {model};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed markPostAsDeleted', error);
|
||||
return {error};
|
||||
}
|
||||
return {model};
|
||||
}
|
||||
|
||||
@@ -9,19 +9,13 @@ import {getEmojiFirstAlias} from '@utils/emoji/helpers';
|
||||
const MAXIMUM_RECENT_EMOJI = 27;
|
||||
|
||||
export const addRecentReaction = async (serverUrl: string, emojiNames: string[], prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
if (!emojiNames.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let recent = await getRecentReactions(database);
|
||||
|
||||
try {
|
||||
if (!emojiNames.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
let recent = await getRecentReactions(database);
|
||||
const recentEmojis = new Set(recent);
|
||||
const aliases = emojiNames.map((e) => getEmojiFirstAlias(e));
|
||||
for (const alias of aliases) {
|
||||
@@ -43,6 +37,8 @@ export const addRecentReaction = async (serverUrl: string, emojiNames: string[],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed addRecentReaction', error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,31 +5,28 @@ import DatabaseManager from '@database/manager';
|
||||
import {prepareDeleteTeam, getMyTeamById, removeTeamFromTeamHistory} from '@queries/servers/team';
|
||||
|
||||
export async function removeUserFromTeam(serverUrl: string, teamId: string) {
|
||||
const serverDatabase = DatabaseManager.serverDatabases[serverUrl];
|
||||
if (!serverDatabase) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {operator, database} = serverDatabase;
|
||||
|
||||
const myTeam = await getMyTeamById(database, teamId);
|
||||
if (myTeam) {
|
||||
const team = await myTeam.team.fetch();
|
||||
if (!team) {
|
||||
return;
|
||||
}
|
||||
const models = await prepareDeleteTeam(team);
|
||||
const system = await removeTeamFromTeamHistory(operator, team.id, true);
|
||||
if (system) {
|
||||
models.push(...system);
|
||||
}
|
||||
if (models.length) {
|
||||
try {
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const myTeam = await getMyTeamById(database, teamId);
|
||||
if (myTeam) {
|
||||
const team = await myTeam.team.fetch();
|
||||
if (!team) {
|
||||
throw new Error('Team not found');
|
||||
}
|
||||
const models = await prepareDeleteTeam(team);
|
||||
const system = await removeTeamFromTeamHistory(operator, team.id, true);
|
||||
if (system) {
|
||||
models.push(...system);
|
||||
}
|
||||
if (models.length) {
|
||||
await operator.batchRecords(models);
|
||||
} catch {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH CHANGES FOR REMOVE USER FROM TEAM');
|
||||
}
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed removeUserFromTeam', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,24 +23,19 @@ import {changeOpacity, setThemeDefaults, updateThemeIfNeeded} from '@utils/theme
|
||||
import type Model from '@nozbe/watermelondb/Model';
|
||||
|
||||
export const switchToGlobalThreads = async (serverUrl: string, teamId?: string, prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
const models: Model[] = [];
|
||||
|
||||
let teamIdToUse = teamId;
|
||||
if (!teamId) {
|
||||
teamIdToUse = await getCurrentTeamId(database);
|
||||
}
|
||||
|
||||
if (!teamIdToUse) {
|
||||
return {error: 'no team to switch to'};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const models: Model[] = [];
|
||||
|
||||
let teamIdToUse = teamId;
|
||||
if (!teamId) {
|
||||
teamIdToUse = await getCurrentTeamId(database);
|
||||
}
|
||||
|
||||
if (!teamIdToUse) {
|
||||
throw new Error('no team to switch to');
|
||||
}
|
||||
|
||||
await setCurrentTeamAndChannelId(operator, teamIdToUse, '');
|
||||
const history = await addChannelToTeamHistory(operator, teamIdToUse, Screens.GLOBAL_THREADS, true);
|
||||
models.push(...history);
|
||||
@@ -55,34 +50,30 @@ export const switchToGlobalThreads = async (serverUrl: string, teamId?: string,
|
||||
} else {
|
||||
goToScreen(Screens.GLOBAL_THREADS, '', {}, {topBar: {visible: false}});
|
||||
}
|
||||
|
||||
return {models};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed switchToGlobalThreads', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {models};
|
||||
};
|
||||
|
||||
export const switchToThread = async (serverUrl: string, rootId: string, isFromNotification = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const user = await getCurrentUser(database);
|
||||
if (!user) {
|
||||
return {error: 'User not found'};
|
||||
throw new Error('User not found');
|
||||
}
|
||||
|
||||
const post = await getPostById(database, rootId);
|
||||
if (!post) {
|
||||
return {error: 'Post not found'};
|
||||
throw new Error('Post not found');
|
||||
}
|
||||
const channel = await getChannelById(database, post.channelId);
|
||||
if (!channel) {
|
||||
return {error: 'Channel not found'};
|
||||
throw new Error('Channel not found');
|
||||
}
|
||||
|
||||
const system = await getCommonSystemValues(database);
|
||||
@@ -180,6 +171,8 @@ export const switchToThread = async (serverUrl: string, rootId: string, isFromNo
|
||||
|
||||
return {};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed switchToThread', error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
@@ -188,105 +181,104 @@ export const switchToThread = async (serverUrl: string, rootId: string, isFromNo
|
||||
// 1. If a reply, then update the reply_count, add user as the participant
|
||||
// 2. Else add the post as a thread
|
||||
export async function createThreadFromNewPost(serverUrl: string, post: Post, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const models: Model[] = [];
|
||||
if (post.root_id) {
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const models: Model[] = [];
|
||||
if (post.root_id) {
|
||||
// Update the thread data: `reply_count`
|
||||
const {model: threadModel} = await updateThread(serverUrl, post.root_id, {reply_count: post.reply_count}, true);
|
||||
if (threadModel) {
|
||||
models.push(threadModel);
|
||||
const {model: threadModel} = await updateThread(serverUrl, post.root_id, {reply_count: post.reply_count}, true);
|
||||
if (threadModel) {
|
||||
models.push(threadModel);
|
||||
}
|
||||
|
||||
// Add user as a participant to the thread
|
||||
const threadParticipantModels = await operator.handleThreadParticipants({
|
||||
threadsParticipants: [{
|
||||
thread_id: post.root_id,
|
||||
participants: [{
|
||||
thread_id: post.root_id,
|
||||
id: post.user_id,
|
||||
}],
|
||||
}],
|
||||
prepareRecordsOnly: true,
|
||||
skipSync: true,
|
||||
});
|
||||
models.push(...threadParticipantModels);
|
||||
} else { // If the post is a root post, then we need to add it to the thread table
|
||||
const threadModels = await prepareThreadsFromReceivedPosts(operator, [post]);
|
||||
models.push(...threadModels);
|
||||
}
|
||||
|
||||
// Add user as a participant to the thread
|
||||
const threadParticipantModels = await operator.handleThreadParticipants({
|
||||
threadsParticipants: [{
|
||||
thread_id: post.root_id,
|
||||
participants: [{
|
||||
thread_id: post.root_id,
|
||||
id: post.user_id,
|
||||
}],
|
||||
}],
|
||||
prepareRecordsOnly: true,
|
||||
skipSync: true,
|
||||
});
|
||||
models.push(...threadParticipantModels);
|
||||
} else { // If the post is a root post, then we need to add it to the thread table
|
||||
const threadModels = await prepareThreadsFromReceivedPosts(operator, [post]);
|
||||
models.push(...threadModels);
|
||||
}
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
return {models};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed createThreadFromNewPost', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {models};
|
||||
}
|
||||
|
||||
// On receiving threads, Along with the "threads" & "thread participants", extract and save "posts" & "users"
|
||||
export async function processReceivedThreads(serverUrl: string, threads: Thread[], teamId: string, loadedInGlobalThreads = false, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
|
||||
const {database} = operator;
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const posts: Post[] = [];
|
||||
const users: UserProfile[] = [];
|
||||
|
||||
const posts: Post[] = [];
|
||||
const users: UserProfile[] = [];
|
||||
// Extract posts & users from the received threads
|
||||
for (let i = 0; i < threads.length; i++) {
|
||||
const {participants, post} = threads[i];
|
||||
posts.push(post);
|
||||
participants.forEach((participant) => {
|
||||
if (currentUserId !== participant.id) {
|
||||
users.push(participant);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Extract posts & users from the received threads
|
||||
for (let i = 0; i < threads.length; i++) {
|
||||
const {participants, post} = threads[i];
|
||||
posts.push(post);
|
||||
participants.forEach((participant) => {
|
||||
if (currentUserId !== participant.id) {
|
||||
users.push(participant);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const postModels = await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [],
|
||||
posts,
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
|
||||
const threadModels = await operator.handleThreads({
|
||||
threads,
|
||||
teamId,
|
||||
prepareRecordsOnly: true,
|
||||
loadedInGlobalThreads,
|
||||
});
|
||||
|
||||
const models = [...postModels, ...threadModels];
|
||||
|
||||
if (users.length) {
|
||||
const userModels = await operator.handleUsers({
|
||||
users,
|
||||
const postModels = await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [],
|
||||
posts,
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
models.push(...userModels);
|
||||
}
|
||||
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
const threadModels = await operator.handleThreads({
|
||||
threads,
|
||||
teamId,
|
||||
prepareRecordsOnly: true,
|
||||
loadedInGlobalThreads,
|
||||
});
|
||||
|
||||
const models = [...postModels, ...threadModels];
|
||||
|
||||
if (users.length) {
|
||||
const userModels = await operator.handleUsers({
|
||||
users,
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
models.push(...userModels);
|
||||
}
|
||||
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords(models);
|
||||
}
|
||||
return {models};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed processReceivedThreads', error);
|
||||
return {error};
|
||||
}
|
||||
return {models};
|
||||
}
|
||||
|
||||
export async function markTeamThreadsAsRead(serverUrl: string, teamId: string, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {database} = operator;
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const threads = await queryThreadsInTeam(database, teamId, true, true, true).fetch();
|
||||
const models = threads.map((thread) => thread.prepareUpdate((record) => {
|
||||
record.unreadMentions = 0;
|
||||
@@ -298,35 +290,35 @@ export async function markTeamThreadsAsRead(serverUrl: string, teamId: string, p
|
||||
}
|
||||
return {models};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed markTeamThreadsAsRead', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateThread(serverUrl: string, threadId: string, updatedThread: Partial<Thread>, prepareRecordsOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const thread = await getThreadById(database, threadId);
|
||||
if (thread) {
|
||||
const model = thread.prepareUpdate((record) => {
|
||||
record.isFollowing = updatedThread.is_following ?? record.isFollowing;
|
||||
record.replyCount = updatedThread.reply_count ?? record.replyCount;
|
||||
|
||||
record.lastViewedAt = updatedThread.last_viewed_at ?? record.lastViewedAt;
|
||||
record.unreadMentions = updatedThread.unread_mentions ?? record.unreadMentions;
|
||||
record.unreadReplies = updatedThread.unread_replies ?? record.unreadReplies;
|
||||
});
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([model]);
|
||||
}
|
||||
return {model};
|
||||
if (!thread) {
|
||||
throw new Error('Thread not found');
|
||||
}
|
||||
return {error: 'Thread not found'};
|
||||
|
||||
const model = thread.prepareUpdate((record) => {
|
||||
record.isFollowing = updatedThread.is_following ?? record.isFollowing;
|
||||
record.replyCount = updatedThread.reply_count ?? record.replyCount;
|
||||
|
||||
record.lastViewedAt = updatedThread.last_viewed_at ?? record.lastViewedAt;
|
||||
record.unreadMentions = updatedThread.unread_mentions ?? record.unreadMentions;
|
||||
record.unreadReplies = updatedThread.unread_replies ?? record.unreadReplies;
|
||||
});
|
||||
if (!prepareRecordsOnly) {
|
||||
await operator.batchRecords([model]);
|
||||
}
|
||||
return {model};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed markTeamThreadsAsRead', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {getTimeZone} from 'react-native-localize';
|
||||
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
export const isTimezoneEnabled = (config: Partial<ClientConfig>) => {
|
||||
return config?.ExperimentalTimezone === 'true';
|
||||
};
|
||||
|
||||
export function getDeviceTimezone() {
|
||||
return getTimeZone();
|
||||
}
|
||||
|
||||
export const getUserTimezone = (currentUser: UserModel) => {
|
||||
if (currentUser?.timezone) {
|
||||
return {
|
||||
...currentUser?.timezone,
|
||||
useAutomaticTimezone: currentUser?.timezone?.useAutomaticTimezone === 'true',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
useAutomaticTimezone: true,
|
||||
automaticTimezone: '',
|
||||
manualTimezone: '',
|
||||
};
|
||||
};
|
||||
@@ -13,107 +13,95 @@ import type Model from '@nozbe/watermelondb/Model';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
export async function setCurrentUserStatusOffline(serverUrl: string) {
|
||||
const serverDatabase = DatabaseManager.serverDatabases[serverUrl];
|
||||
if (!serverDatabase) {
|
||||
return {error: `No database present for ${serverUrl}`};
|
||||
}
|
||||
|
||||
const {database, operator} = serverDatabase;
|
||||
|
||||
const user = await getCurrentUser(database);
|
||||
if (!user) {
|
||||
return {error: `No current user for ${serverUrl}`};
|
||||
}
|
||||
|
||||
user.prepareStatus(General.OFFLINE);
|
||||
|
||||
try {
|
||||
await operator.batchRecords([user]);
|
||||
} catch {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH CHANGES FOR SET CURRENT USER STATUS OFFLINE');
|
||||
}
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const user = await getCurrentUser(database);
|
||||
if (!user) {
|
||||
throw new Error(`No current user for ${serverUrl}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
user.prepareStatus(General.OFFLINE);
|
||||
await operator.batchRecords([user]);
|
||||
return null;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed setCurrentUserStatusOffline', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateLocalCustomStatus(serverUrl: string, user: UserModel, customStatus?: UserCustomStatus) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const models: Model[] = [];
|
||||
const currentProps = {...user.props, customStatus: customStatus || {}};
|
||||
const userModel = user.prepareUpdate((u: UserModel) => {
|
||||
u.props = currentProps;
|
||||
});
|
||||
|
||||
const models: Model[] = [];
|
||||
const currentProps = {...user.props, customStatus: customStatus || {}};
|
||||
const userModel = user.prepareUpdate((u: UserModel) => {
|
||||
u.props = currentProps;
|
||||
});
|
||||
models.push(userModel);
|
||||
if (customStatus) {
|
||||
const recent = await updateRecentCustomStatuses(serverUrl, customStatus, true);
|
||||
if (Array.isArray(recent)) {
|
||||
models.push(...recent);
|
||||
}
|
||||
|
||||
models.push(userModel);
|
||||
if (customStatus) {
|
||||
const recent = await updateRecentCustomStatuses(serverUrl, customStatus, true);
|
||||
if (Array.isArray(recent)) {
|
||||
models.push(...recent);
|
||||
}
|
||||
|
||||
if (customStatus.emoji) {
|
||||
const recentEmojis = await addRecentReaction(serverUrl, [customStatus.emoji], true);
|
||||
if (Array.isArray(recentEmojis)) {
|
||||
models.push(...recentEmojis);
|
||||
if (customStatus.emoji) {
|
||||
const recentEmojis = await addRecentReaction(serverUrl, [customStatus.emoji], true);
|
||||
if (Array.isArray(recentEmojis)) {
|
||||
models.push(...recentEmojis);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await operator.batchRecords(models);
|
||||
} catch {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('FAILED TO BATCH CHANGES FOR UPDATING CUSTOM STATUS');
|
||||
}
|
||||
|
||||
return {};
|
||||
return {};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateLocalCustomStatus', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const updateRecentCustomStatuses = async (serverUrl: string, customStatus: UserCustomStatus, prepareRecordsOnly = false, remove = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const recentStatuses = await getRecentCustomStatuses(operator.database);
|
||||
const index = recentStatuses.findIndex((cs) => (
|
||||
cs.emoji === customStatus.emoji &&
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const recentStatuses = await getRecentCustomStatuses(database);
|
||||
const index = recentStatuses.findIndex((cs) => (
|
||||
cs.emoji === customStatus.emoji &&
|
||||
cs.text === customStatus.text &&
|
||||
cs.duration === customStatus.duration
|
||||
));
|
||||
));
|
||||
|
||||
if (index !== -1) {
|
||||
recentStatuses.splice(index, 1);
|
||||
if (index !== -1) {
|
||||
recentStatuses.splice(index, 1);
|
||||
}
|
||||
|
||||
if (!remove) {
|
||||
recentStatuses.unshift(customStatus);
|
||||
}
|
||||
|
||||
return operator.handleSystem({
|
||||
systems: [{
|
||||
id: SYSTEM_IDENTIFIERS.RECENT_CUSTOM_STATUS,
|
||||
value: JSON.stringify(recentStatuses),
|
||||
}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateRecentCustomStatuses', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
if (!remove) {
|
||||
recentStatuses.unshift(customStatus);
|
||||
}
|
||||
|
||||
return operator.handleSystem({
|
||||
systems: [{
|
||||
id: SYSTEM_IDENTIFIERS.RECENT_CUSTOM_STATUS,
|
||||
value: JSON.stringify(recentStatuses),
|
||||
}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
};
|
||||
|
||||
export const updateLocalUser = async (
|
||||
serverUrl: string,
|
||||
userDetails: Partial<UserProfile> & { status?: string},
|
||||
) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const user = await getCurrentUser(database);
|
||||
if (user) {
|
||||
await database.write(async () => {
|
||||
@@ -135,21 +123,17 @@ export const updateLocalUser = async (
|
||||
});
|
||||
});
|
||||
}
|
||||
return {user};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed updateLocalUser', error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
export const storeProfile = async (serverUrl: string, profile: UserProfile) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const user = await getUserById(database, profile.id);
|
||||
if (user) {
|
||||
return {user};
|
||||
@@ -162,6 +146,8 @@ export const storeProfile = async (serverUrl: string, profile: UserProfile) => {
|
||||
|
||||
return {user: records[0]};
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Failed storeProfile', error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
import {DeviceEventEmitter} from 'react-native';
|
||||
|
||||
import {getDeviceTimezone, isTimezoneEnabled} from '@actions/local/timezone';
|
||||
import {Database, Events} from '@constants';
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
@@ -14,6 +13,7 @@ import {getDeviceToken} from '@queries/app/global';
|
||||
import {getCurrentUserId, getCommonSystemValues} from '@queries/servers/system';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {getCSRFFromCookie} from '@utils/security';
|
||||
import {getDeviceTimezone, isTimezoneEnabled} from '@utils/timezone';
|
||||
|
||||
import {loginEntry} from './entry';
|
||||
import {fetchDataRetentionPolicy} from './systems';
|
||||
|
||||
@@ -7,7 +7,6 @@ import {Model} from '@nozbe/watermelondb';
|
||||
import {chunk} from 'lodash';
|
||||
|
||||
import {updateChannelsDisplayName} from '@actions/local/channel';
|
||||
import {getUserTimezone} from '@actions/local/timezone';
|
||||
import {updateRecentCustomStatuses, updateLocalUser} from '@actions/local/user';
|
||||
import {fetchRolesIfNeeded} from '@actions/remote/role';
|
||||
import {General} from '@constants';
|
||||
@@ -17,7 +16,7 @@ import NetworkManager from '@managers/network_manager';
|
||||
import {getMembersCountByChannelsId, queryChannelsByTypes} from '@queries/servers/channel';
|
||||
import {getCurrentTeamId, getCurrentUserId} from '@queries/servers/system';
|
||||
import {getCurrentUser, getUserById, prepareUsers, queryAllUsers, queryUsersById, queryUsersByUsername} from '@queries/servers/user';
|
||||
import {removeUserFromList} from '@utils/user';
|
||||
import {getUserTimezoneProps, removeUserFromList} from '@utils/user';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
@@ -804,7 +803,7 @@ export const autoUpdateTimezone = async (serverUrl: string, {deviceTimezone, use
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentTimezone = getUserTimezone(currentUser);
|
||||
const currentTimezone = getUserTimezoneProps(currentUser);
|
||||
const newTimezoneExists = currentTimezone.automaticTimezone !== deviceTimezone;
|
||||
|
||||
if (currentTimezone.useAutomaticTimezone && newTimezoneExists) {
|
||||
|
||||
@@ -9,7 +9,6 @@ import {Text, TextStyle} from 'react-native';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
|
||||
import {getUserTimezone} from '@actions/local/timezone';
|
||||
import FormattedDate from '@components/formatted_date';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import FormattedTime from '@components/formatted_time';
|
||||
@@ -19,6 +18,7 @@ import {queryPreferencesByCategoryAndName} from '@queries/servers/preference';
|
||||
import {observeCurrentUser} from '@queries/servers/user';
|
||||
import {getCurrentMomentForTimezone} from '@utils/helpers';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {getUserTimezoneProps} from '@utils/user';
|
||||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
@@ -46,7 +46,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
||||
});
|
||||
|
||||
const CustomStatusExpiry = ({currentUser, isMilitaryTime, showPrefix, showTimeCompulsory, showToday, testID = '', textStyles = {}, theme, time, withinBrackets}: Props) => {
|
||||
const userTimezone = getUserTimezone(currentUser);
|
||||
const userTimezone = getUserTimezoneProps(currentUser);
|
||||
const timezone = userTimezone.useAutomaticTimezone ? userTimezone.automaticTimezone : userTimezone.manualTimezone;
|
||||
const styles = getStyleSheet(theme);
|
||||
const currentMomentTime = getCurrentMomentForTimezone(timezone);
|
||||
|
||||
@@ -229,6 +229,24 @@ class DatabaseManager {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
public getAppDatabaseAndOperator = () => {
|
||||
const app = this.appDatabase;
|
||||
if (!app) {
|
||||
throw new Error('App database not found');
|
||||
}
|
||||
|
||||
return app;
|
||||
};
|
||||
|
||||
public getServerDatabaseAndOperator = (serverUrl: string) => {
|
||||
const server = this.serverDatabases[serverUrl];
|
||||
if (!server) {
|
||||
throw new Error(`${serverUrl} database not found`);
|
||||
}
|
||||
|
||||
return server;
|
||||
};
|
||||
|
||||
public getActiveServerDatabase = async (): Promise<Database|undefined> => {
|
||||
const database = this.appDatabase?.database;
|
||||
if (database) {
|
||||
|
||||
@@ -307,6 +307,38 @@ class DatabaseManager {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* getAppDatabaseAndOperator: Helper function that returns App the database and operator.
|
||||
* use within a try/catch block
|
||||
* @returns AppDatabase
|
||||
* @throws Error
|
||||
*/
|
||||
public getAppDatabaseAndOperator = () => {
|
||||
const app = this.appDatabase;
|
||||
if (!app) {
|
||||
throw new Error('App database not found');
|
||||
}
|
||||
|
||||
return app;
|
||||
};
|
||||
|
||||
/**
|
||||
* getServerDatabaseAndOperator: Helper function that returns the database and operator
|
||||
* for a specific server.
|
||||
* use within a try/catch block
|
||||
* @param serverUrl the url of the server
|
||||
* @returns ServerDatabase
|
||||
* @throws Error
|
||||
*/
|
||||
public getServerDatabaseAndOperator = (serverUrl: string) => {
|
||||
const server = this.serverDatabases[serverUrl];
|
||||
if (!server) {
|
||||
throw new Error(`${serverUrl} database not found`);
|
||||
}
|
||||
|
||||
return server;
|
||||
};
|
||||
|
||||
/**
|
||||
* setActiveServerDatabase: Set the new active server database.
|
||||
* This method should be called when switching to another server.
|
||||
|
||||
12
app/utils/timezone.ts
Normal file
12
app/utils/timezone.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {getTimeZone} from 'react-native-localize';
|
||||
|
||||
export const isTimezoneEnabled = (config: Partial<ClientConfig>) => {
|
||||
return config?.ExperimentalTimezone === 'true';
|
||||
};
|
||||
|
||||
export function getDeviceTimezone() {
|
||||
return getTimeZone();
|
||||
}
|
||||
@@ -101,6 +101,21 @@ export const getUsersByUsername = (users: UserModel[]) => {
|
||||
return usersByUsername;
|
||||
};
|
||||
|
||||
export const getUserTimezoneProps = (currentUser: UserModel) => {
|
||||
if (currentUser?.timezone) {
|
||||
return {
|
||||
...currentUser?.timezone,
|
||||
useAutomaticTimezone: currentUser?.timezone?.useAutomaticTimezone === 'true',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
useAutomaticTimezone: true,
|
||||
automaticTimezone: '',
|
||||
manualTimezone: '',
|
||||
};
|
||||
};
|
||||
|
||||
export const getUserTimezone = (user: UserModel) => {
|
||||
return getTimezone(user.timezone);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user