Refactor errors around the app (#7306)
* Refactor errors around the app * Fix recursive function * Fix tests
This commit is contained in:
parent
e06f85d408
commit
86658edc30
82 changed files with 1079 additions and 1959 deletions
|
|
@ -5,9 +5,10 @@ import {sendEphemeralPost} from '@actions/local/post';
|
|||
import {AppCallResponseTypes} from '@constants/apps';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {cleanForm, createCallRequest, makeCallErrorResponse} from '@utils/apps';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
|
|
@ -58,15 +59,9 @@ export async function handleBindingClick<Res=unknown>(serverUrl: string, binding
|
|||
return doAppSubmit<Res>(serverUrl, callRequest, intl);
|
||||
}
|
||||
|
||||
export async function doAppSubmit<Res=unknown>(serverUrl: string, inCall: AppCallRequest, intl: IntlShape) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: makeCallErrorResponse((error as ClientError).message)};
|
||||
}
|
||||
|
||||
export async function doAppSubmit<Res=unknown>(serverUrl: string, inCall: AppCallRequest, intl: IntlShape): Promise<{data: AppCallResponse<Res>} | {error: AppCallResponse<Res>}> {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const call: AppCallRequest = {
|
||||
...inCall,
|
||||
context: {
|
||||
|
|
@ -116,23 +111,18 @@ export async function doAppSubmit<Res=unknown>(serverUrl: string, inCall: AppCal
|
|||
}
|
||||
}
|
||||
} catch (error) {
|
||||
const errMsg = (error as ClientError).message || intl.formatMessage({
|
||||
const errMsg = getFullErrorMessage(error) || intl.formatMessage({
|
||||
id: 'apps.error.responses.unexpected_error',
|
||||
defaultMessage: 'Received an unexpected error.',
|
||||
});
|
||||
logDebug('error on doAppSubmit', getFullErrorMessage(error));
|
||||
return {error: makeCallErrorResponse(errMsg)};
|
||||
}
|
||||
}
|
||||
|
||||
export async function doAppFetchForm<Res=unknown>(serverUrl: string, call: AppCallRequest, intl: IntlShape) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: makeCallErrorResponse((error as ClientError).message)};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const res = await client.executeAppCall<Res>(call, false);
|
||||
const responseType = res.type || AppCallResponseTypes.OK;
|
||||
|
||||
|
|
@ -157,11 +147,12 @@ export async function doAppFetchForm<Res=unknown>(serverUrl: string, call: AppCa
|
|||
return {error: makeCallErrorResponse(errMsg)};
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
const errMsg = error.message || intl.formatMessage({
|
||||
} catch (error) {
|
||||
const errMsg = getFullErrorMessage(error) || intl.formatMessage({
|
||||
id: 'apps.error.responses.unexpected_error',
|
||||
defaultMessage: 'Received an unexpected error.',
|
||||
});
|
||||
logDebug('error on doAppFetchForm', getFullErrorMessage(error));
|
||||
return {error: makeCallErrorResponse(errMsg)};
|
||||
}
|
||||
}
|
||||
|
|
@ -170,11 +161,6 @@ export async function doAppLookup<Res=unknown>(serverUrl: string, call: AppCallR
|
|||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: makeCallErrorResponse((error as ClientError).message)};
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await client.executeAppCall<Res>(call, false);
|
||||
const responseType = res.type || AppCallResponseTypes.OK;
|
||||
|
||||
|
|
@ -193,10 +179,11 @@ export async function doAppLookup<Res=unknown>(serverUrl: string, call: AppCallR
|
|||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
const errMsg = error.message || intl.formatMessage({
|
||||
const errMsg = getFullErrorMessage(error) || intl.formatMessage({
|
||||
id: 'apps.error.responses.unexpected_error',
|
||||
defaultMessage: 'Received an unexpected error.',
|
||||
});
|
||||
logDebug('error on doAppLookup', getFullErrorMessage(error));
|
||||
return {error: makeCallErrorResponse(errMsg)};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,26 +9,20 @@ import NetworkManager from '@managers/network_manager';
|
|||
import {getChannelCategory, queryCategoriesByTeamIds} from '@queries/servers/categories';
|
||||
import {getChannelById} from '@queries/servers/channel';
|
||||
import {getCurrentTeamId} from '@queries/servers/system';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {showFavoriteChannelSnackbar} from '@utils/snack_bar';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
|
||||
export type CategoriesRequest = {
|
||||
categories?: CategoryWithChannels[];
|
||||
error?: unknown;
|
||||
}
|
||||
|
||||
export const fetchCategories = async (serverUrl: string, teamId: string, prune = false, fetchOnly = false): Promise<CategoriesRequest> => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {categories} = await client.getCategories('me', teamId);
|
||||
|
||||
if (!fetchOnly) {
|
||||
|
|
@ -37,26 +31,17 @@ export const fetchCategories = async (serverUrl: string, teamId: string, prune =
|
|||
|
||||
return {categories};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchCategories', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const toggleFavoriteChannel = async (serverUrl: string, channelId: string, showSnackBar = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (!channel) {
|
||||
return {error: 'channel not found'};
|
||||
|
|
@ -109,7 +94,8 @@ export const toggleFavoriteChannel = async (serverUrl: string, channelId: string
|
|||
|
||||
return {data: true};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on toggleFavoriteChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import {dismissAllModalsAndPopToRoot} from '@screens/navigation';
|
|||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {setTeamLoading} from '@store/team_load_store';
|
||||
import {generateChannelNameFromDisplayName, getDirectChannelName, isDMorGM} from '@utils/channel';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {isTablet} from '@utils/helpers';
|
||||
import {logDebug, logError, logInfo} from '@utils/log';
|
||||
import {showMuteChannelSnackbar} from '@utils/snack_bar';
|
||||
|
|
@ -38,8 +39,6 @@ import {forceLogoutIfNecessary} from './session';
|
|||
import {addCurrentUserToTeam, fetchTeamByName, removeCurrentUserFromTeam} from './team';
|
||||
import {fetchProfilesInChannel, fetchProfilesInGroupChannels, fetchProfilesPerChannels, fetchUsersByIds, updateUsersNoLongerVisible} from './user';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {Model} from '@nozbe/watermelondb';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
|
@ -64,10 +63,10 @@ export async function removeMemberFromChannel(serverUrl: string, channelId: stri
|
|||
await client.removeFromChannel(userId, channelId);
|
||||
await deleteChannelMembership(operator, userId, channelId);
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
logError('removeMemberFromChannel', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on removeMemberFromChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -94,8 +93,8 @@ export async function fetchChannelMembersByIds(serverUrl: string, channelId: str
|
|||
|
||||
return {members};
|
||||
} catch (error) {
|
||||
logError('fetchChannelMembersByIds', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchChannelMembersByIds', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -108,10 +107,10 @@ export async function updateChannelMemberSchemeRoles(serverUrl: string, channelI
|
|||
return getMemberInChannel(serverUrl, channelId, userId);
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
logError('updateChannelMemberSchemeRoles', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on updateChannelMemberSchemeRoles', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -124,10 +123,10 @@ export async function getMemberInChannel(serverUrl: string, channelId: string, u
|
|||
if (!fetchOnly) {
|
||||
updateLocalUser(serverUrl, member, userId);
|
||||
}
|
||||
return {member, error: undefined};
|
||||
return {member};
|
||||
} catch (error) {
|
||||
logError('getMemberInChannel', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on getMemberInChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -145,19 +144,9 @@ export async function fetchChannelMemberships(serverUrl: string, channelId: stri
|
|||
}
|
||||
|
||||
export async function addMembersToChannel(serverUrl: string, channelId: string, userIds: string[], postRootId = '', fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const promises = userIds.map((id) => client.addToChannel(id, channelId, postRootId));
|
||||
const channelMemberships: ChannelMembership[] = await Promise.all(promises);
|
||||
const {users} = await fetchUsersByIds(serverUrl, userIds, true);
|
||||
|
|
@ -180,51 +169,37 @@ export async function addMembersToChannel(serverUrl: string, channelId: string,
|
|||
}
|
||||
return {channelMemberships};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on addMembersToChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchChannelByName(serverUrl: string, teamId: string, channelName: string, fetchOnly = false) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const channel = await client.getChannelByName(teamId, channelName, true);
|
||||
|
||||
if (!fetchOnly) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (operator) {
|
||||
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
|
||||
}
|
||||
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
|
||||
}
|
||||
|
||||
return {channel};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchChannelByName', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function createChannel(serverUrl: string, displayName: string, purpose: string, header: string, type: ChannelType) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
EphemeralStore.creatingChannel = true;
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const {currentUserId, currentTeamId} = await getCommonSystemValues(database);
|
||||
const name = generateChannelNameFromDisplayName(displayName);
|
||||
const channel = {
|
||||
|
|
@ -237,7 +212,6 @@ export async function createChannel(serverUrl: string, displayName: string, purp
|
|||
type,
|
||||
} as Channel;
|
||||
|
||||
EphemeralStore.creatingChannel = true;
|
||||
const channelData = await client.createChannel(channel);
|
||||
|
||||
const member = await client.getChannelMember(channelData.id, currentUserId);
|
||||
|
|
@ -259,29 +233,21 @@ export async function createChannel(serverUrl: string, displayName: string, purp
|
|||
EphemeralStore.creatingChannel = false;
|
||||
return {channel: channelData};
|
||||
} catch (error) {
|
||||
logDebug('error on createChannel', getFullErrorMessage(error));
|
||||
EphemeralStore.creatingChannel = false;
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function patchChannel(serverUrl: string, channelPatch: Partial<Channel> & {id: string}) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const channelData = await client.patchChannel(channelPatch.id, channelPatch);
|
||||
const models = [];
|
||||
const channelInfo = (await getChannelInfo(operator.database, channelData.id));
|
||||
const channelInfo = (await getChannelInfo(database, channelData.id));
|
||||
if (channelInfo && (channelInfo.purpose !== channelData.purpose || channelInfo.header !== channelData.header)) {
|
||||
channelInfo.prepareUpdate((v) => {
|
||||
v.purpose = channelData.purpose;
|
||||
|
|
@ -289,7 +255,7 @@ export async function patchChannel(serverUrl: string, channelPatch: Partial<Chan
|
|||
});
|
||||
models.push(channelInfo);
|
||||
}
|
||||
const channel = await getChannelById(operator.database, channelData.id);
|
||||
const channel = await getChannelById(database, channelData.id);
|
||||
if (channel && (channel.displayName !== channelData.display_name || channel.type !== channelData.type)) {
|
||||
channel.prepareUpdate((v) => {
|
||||
v.displayName = channelData.display_name;
|
||||
|
|
@ -302,26 +268,18 @@ export async function patchChannel(serverUrl: string, channelPatch: Partial<Chan
|
|||
}
|
||||
return {channel: channelData};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on patchChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function leaveChannel(serverUrl: string, channelId: string) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
EphemeralStore.addLeavingChannel(channelId);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const isTabletDevice = await isTablet();
|
||||
const user = await getCurrentUser(database);
|
||||
const models: Model[] = [];
|
||||
|
|
@ -330,7 +288,6 @@ export async function leaveChannel(serverUrl: string, channelId: string) {
|
|||
return {error: 'current user not found'};
|
||||
}
|
||||
|
||||
EphemeralStore.addLeavingChannel(channelId);
|
||||
await client.removeFromChannel(user.id, channelId);
|
||||
|
||||
if (user.isGuest) {
|
||||
|
|
@ -352,9 +309,10 @@ export async function leaveChannel(serverUrl: string, channelId: string) {
|
|||
} else {
|
||||
setCurrentChannelId(operator, '');
|
||||
}
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on leaveChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
} finally {
|
||||
EphemeralStore.removeLeavingChannel(channelId);
|
||||
|
|
@ -362,21 +320,12 @@ export async function leaveChannel(serverUrl: string, channelId: string) {
|
|||
}
|
||||
|
||||
export async function fetchChannelCreator(serverUrl: string, channelId: string, fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const channel = await getChannelById(operator.database, channelId);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (channel && channel.creatorId) {
|
||||
const user = await client.getUser(channel.creatorId);
|
||||
|
||||
|
|
@ -403,28 +352,20 @@ export async function fetchChannelCreator(serverUrl: string, channelId: string,
|
|||
|
||||
return {user: undefined};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchChannelCreator', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchChannelStats(serverUrl: string, channelId: string, fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const stats = await client.getChannelStats(channelId);
|
||||
if (!fetchOnly) {
|
||||
const channel = await getChannelById(operator.database, channelId);
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (channel) {
|
||||
const channelInfos: Array<Partial<ChannelInfo>> = [{
|
||||
guest_count: stats.guest_count,
|
||||
|
|
@ -439,28 +380,19 @@ export async function fetchChannelStats(serverUrl: string, channelId: string, fe
|
|||
|
||||
return {stats};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchChannelStats', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchMyChannelsForTeam(serverUrl: string, teamId: string, includeDeleted = true, since = 0, fetchOnly = false, excludeDirect = false, isCRTEnabled?: boolean): Promise<MyChannelsRequest> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
if (!fetchOnly) {
|
||||
setTeamLoading(serverUrl, true);
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const [allChannels, channelMemberships, categoriesWithOrder] = await Promise.all([
|
||||
client.getMyChannels(teamId, includeDeleted, since),
|
||||
client.getMyChannelMembers(teamId),
|
||||
|
|
@ -494,28 +426,19 @@ export async function fetchMyChannelsForTeam(serverUrl: string, teamId: string,
|
|||
|
||||
return {channels, memberships, categories};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchMyChannelsForTeam', getFullErrorMessage(error));
|
||||
if (!fetchOnly) {
|
||||
setTeamLoading(serverUrl, false);
|
||||
}
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchMyChannel(serverUrl: string, teamId: string, channelId: string, fetchOnly = false): Promise<MyChannelsRequest> {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
try {
|
||||
const [channel, member] = await Promise.all([
|
||||
client.getChannel(channelId),
|
||||
client.getChannelMember(channelId, 'me'),
|
||||
|
|
@ -530,7 +453,8 @@ export async function fetchMyChannel(serverUrl: string, teamId: string, channelI
|
|||
memberships: [member],
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchMyChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -617,6 +541,7 @@ export async function fetchMissingDirectChannelsInfo(serverUrl: string, directCh
|
|||
|
||||
return {directChannels: updatedChannelsArray, users};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchMissingDirectChannelsInfo', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -637,24 +562,15 @@ export async function fetchDirectChannelsInfo(serverUrl: string, directChannels:
|
|||
}
|
||||
|
||||
export async function joinChannel(serverUrl: string, teamId: string, channelId?: string, channelName?: string, fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const database = operator.database;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
const userId = await getCurrentUserId(database);
|
||||
|
||||
let member: ChannelMembership | undefined;
|
||||
let channel: Channel | undefined;
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const userId = await getCurrentUserId(database);
|
||||
|
||||
if (channelId) {
|
||||
EphemeralStore.addJoiningChannel(channelId);
|
||||
member = await client.addToChannel(userId, channelId);
|
||||
|
|
@ -668,15 +584,7 @@ export async function joinChannel(serverUrl: string, teamId: string, channelId?:
|
|||
member = await client.addToChannel(userId, channel.id);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (channelId || channel?.id) {
|
||||
EphemeralStore.removeJoiningChannel(channelId || channel!.id);
|
||||
}
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
if (channel && member && !fetchOnly) {
|
||||
fetchRolesIfNeeded(serverUrl, member.roles.split(' '));
|
||||
|
||||
|
|
@ -698,9 +606,11 @@ export async function joinChannel(serverUrl: string, teamId: string, channelId?:
|
|||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logDebug('error on joinChannel', getFullErrorMessage(error));
|
||||
if (channelId || channel?.id) {
|
||||
EphemeralStore.removeJoiningChannel(channelId || channel!.id);
|
||||
}
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
|
|
@ -712,15 +622,12 @@ export async function joinChannel(serverUrl: string, teamId: string, channelId?:
|
|||
}
|
||||
|
||||
export async function joinChannelIfNeeded(serverUrl: string, channelId: string) {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const myChannel = await getMyChannel(database, channelId);
|
||||
if (myChannel) {
|
||||
return {error: undefined};
|
||||
return {};
|
||||
}
|
||||
|
||||
return joinChannel(serverUrl, '', channelId);
|
||||
|
|
@ -740,19 +647,12 @@ export async function markChannelAsRead(serverUrl: string, channelId: string, up
|
|||
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on markChannelAsRead', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function switchToChannelByName(serverUrl: string, channelName: string, teamName: string, errorHandler: (intl: IntlShape) => void, intl: IntlShape) {
|
||||
let database;
|
||||
try {
|
||||
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
database = result.database;
|
||||
} catch (e) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const onError = (joinedTeam: boolean, teamId?: string) => {
|
||||
errorHandler(intl);
|
||||
if (joinedTeam && teamId) {
|
||||
|
|
@ -762,7 +662,10 @@ export async function switchToChannelByName(serverUrl: string, channelName: stri
|
|||
|
||||
let joinedTeam = false;
|
||||
let teamId = '';
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
if (teamName === DeepLink.Redirect) {
|
||||
teamId = await getCurrentTeamId(database);
|
||||
} else {
|
||||
|
|
@ -814,7 +717,7 @@ export async function switchToChannelByName(serverUrl: string, channelName: stri
|
|||
}
|
||||
|
||||
switchToChannelById(serverUrl, channelId, teamId);
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
onError(joinedTeam, teamId);
|
||||
return {error};
|
||||
|
|
@ -822,14 +725,8 @@ export async function switchToChannelByName(serverUrl: string, channelName: stri
|
|||
}
|
||||
|
||||
export async function goToNPSChannel(serverUrl: string) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const user = await client.getUserByUsername(General.NPS_PLUGIN_BOT_USERNAME);
|
||||
const {data, error} = await createDirectChannel(serverUrl, user.id);
|
||||
if (error || !data) {
|
||||
|
|
@ -837,7 +734,8 @@ export async function goToNPSChannel(serverUrl: string) {
|
|||
}
|
||||
await switchToChannelById(serverUrl, data.id, data.team_id);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on goToNPSChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
|
|
@ -845,20 +743,10 @@ export async function goToNPSChannel(serverUrl: string) {
|
|||
}
|
||||
|
||||
export async function createDirectChannel(serverUrl: string, userId: string, displayName = '') {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
EphemeralStore.creatingDMorGMTeammates = [userId];
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const currentUser = await getCurrentUser(database);
|
||||
if (!currentUser) {
|
||||
return {error: 'Cannot get the current user'};
|
||||
|
|
@ -870,7 +758,6 @@ export async function createDirectChannel(serverUrl: string, userId: string, dis
|
|||
return {data: channel.toApi()};
|
||||
}
|
||||
|
||||
EphemeralStore.creatingDMorGMTeammates = [userId];
|
||||
const created = await client.createDirectChannel([userId, currentUser.id]);
|
||||
const profiles: UserProfile[] = [];
|
||||
|
||||
|
|
@ -925,40 +812,32 @@ export async function createDirectChannel(serverUrl: string, userId: string, dis
|
|||
fetchRolesIfNeeded(serverUrl, member.roles.split(' '));
|
||||
return {data: created};
|
||||
} catch (error) {
|
||||
logDebug('error on createDirectChannel', getFullErrorMessage(error));
|
||||
EphemeralStore.creatingDMorGMTeammates = [];
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchChannels(serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const channels = await client.getChannels(teamId, page, perPage);
|
||||
|
||||
return {channels};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchChannels', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function makeDirectChannel(serverUrl: string, userId: string, displayName = '', shouldSwitchToChannel = true) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const channelName = getDirectChannelName(userId, currentUserId);
|
||||
let channel: Channel|ChannelModel|undefined = await getChannelByName(operator.database, '', channelName);
|
||||
let channel: Channel|ChannelModel|undefined = await getChannelByName(database, '', channelName);
|
||||
let result: {data?: Channel|ChannelModel; error?: any};
|
||||
if (channel) {
|
||||
result = {data: channel};
|
||||
|
|
@ -978,38 +857,28 @@ export async function makeDirectChannel(serverUrl: string, userId: string, displ
|
|||
}
|
||||
|
||||
export async function fetchArchivedChannels(serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const channels = await client.getArchivedChannels(teamId, page, perPage);
|
||||
|
||||
return {channels};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchArchivedChannels', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function createGroupChannel(serverUrl: string, userIds: string[]) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
EphemeralStore.creatingDMorGMTeammates = userIds;
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const currentUser = await getCurrentUser(database);
|
||||
if (!currentUser) {
|
||||
return {error: 'Cannot get the current user'};
|
||||
}
|
||||
EphemeralStore.creatingDMorGMTeammates = userIds;
|
||||
|
||||
const created = await client.createGroupChannel(userIds);
|
||||
|
||||
// Check the channel previous existency: if the channel already have
|
||||
|
|
@ -1061,37 +930,30 @@ export async function createGroupChannel(serverUrl: string, userIds: string[]) {
|
|||
fetchRolesIfNeeded(serverUrl, member.roles.split(' '));
|
||||
return {data: created};
|
||||
} catch (error) {
|
||||
logDebug('error on createGroupChannel', getFullErrorMessage(error));
|
||||
EphemeralStore.creatingDMorGMTeammates = [];
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchSharedChannels(serverUrl: string, teamId: string, page = 0, perPage: number = General.CHANNELS_CHUNK_SIZE) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const channels = await client.getSharedChannels(teamId, page, perPage);
|
||||
|
||||
return {channels};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchSharedChannels', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function makeGroupChannel(serverUrl: string, userIds: string[], shouldSwitchToChannel = true) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const result = await createGroupChannel(serverUrl, [currentUserId, ...userIds]);
|
||||
const channel = result.data;
|
||||
|
||||
|
|
@ -1106,33 +968,23 @@ export async function makeGroupChannel(serverUrl: string, userIds: string[], sho
|
|||
}
|
||||
|
||||
export async function getChannelMemberCountsByGroup(serverUrl: string, channelId: string, includeTimezones: boolean) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const channelMemberCountsByGroup = await client.getChannelMemberCountsByGroup(channelId, includeTimezones);
|
||||
return {channelMemberCountsByGroup};
|
||||
} catch (error) {
|
||||
logDebug('error on getChannelMemberCountsByGroup', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function getChannelTimezones(serverUrl: string, channelId: string) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const channelTimezones = await client.getChannelTimezones(channelId);
|
||||
return {channelTimezones};
|
||||
} catch (error) {
|
||||
logDebug('error on getChannelTimezones', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -1166,12 +1018,8 @@ export async function switchToChannelById(serverUrl: string, channelId: string,
|
|||
}
|
||||
|
||||
export async function switchToPenultimateChannel(serverUrl: string, teamId?: string) {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const teamIdToUse = teamId || await getCurrentTeamId(database);
|
||||
const channelId = await getNthLastChannelFromTeam(database, teamIdToUse, 1);
|
||||
return switchToChannelById(serverUrl, channelId);
|
||||
|
|
@ -1181,12 +1029,8 @@ export async function switchToPenultimateChannel(serverUrl: string, teamId?: str
|
|||
}
|
||||
|
||||
export async function switchToLastChannel(serverUrl: string, teamId?: string) {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const teamIdToUse = teamId || await getCurrentTeamId(database);
|
||||
const channelId = await getNthLastChannelFromTeam(database, teamIdToUse);
|
||||
return switchToChannelById(serverUrl, channelId);
|
||||
|
|
@ -1196,79 +1040,45 @@ export async function switchToLastChannel(serverUrl: string, teamId?: string) {
|
|||
}
|
||||
|
||||
export async function searchChannels(serverUrl: string, term: string, teamId: string, isSearch = false) {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const autoCompleteFunc = isSearch ? client.autocompleteChannelsForSearch : client.autocompleteChannels;
|
||||
const channels = await autoCompleteFunc(teamId, term);
|
||||
return {channels};
|
||||
} catch (error) {
|
||||
logDebug('error on searchChannels', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchChannelById(serverUrl: string, id: string) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const channel = await client.getChannel(id);
|
||||
return {channel};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchChannelById', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function searchAllChannels(serverUrl: string, term: string, archivedOnly = false) {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const myTeamIds = await queryMyTeams(database).fetchIds();
|
||||
const channels = await client.searchAllChannels(term, myTeamIds, archivedOnly);
|
||||
return {channels};
|
||||
} catch (error) {
|
||||
logDebug('error on searchAllChannels', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const updateChannelNotifyProps = async (serverUrl: string, channelId: string, props: Partial<ChannelNotifyProps>) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const userId = await getCurrentUserId(database);
|
||||
const notifyProps = {...props, channel_id: channelId, user_id: userId} as ChannelNotifyProps & {channel_id: string; user_id: string};
|
||||
|
||||
|
|
@ -1278,18 +1088,15 @@ export const updateChannelNotifyProps = async (serverUrl: string, channelId: str
|
|||
notifyProps,
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on updateChannelNotifyProps', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const toggleMuteChannel = async (serverUrl: string, channelId: string, showSnackBar = false) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const channelSettings = await queryMyChannelSettingsByIds(database, [channelId]).fetch();
|
||||
const myChannelSetting = channelSettings?.[0];
|
||||
const mark_unread = myChannelSetting.notifyProps?.mark_unread === 'mention' ? 'all' : 'mention';
|
||||
|
|
@ -1317,22 +1124,11 @@ export const toggleMuteChannel = async (serverUrl: string, channelId: string, sh
|
|||
};
|
||||
|
||||
export const archiveChannel = async (serverUrl: string, channelId: string) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const config = await getConfig(database);
|
||||
EphemeralStore.addArchivingChannel(channelId);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const config = await getConfig(database);
|
||||
await client.deleteChannel(channelId);
|
||||
if (config?.ExperimentalViewArchivedChannels === 'true') {
|
||||
await setChannelDeleteAt(serverUrl, channelId, Date.now());
|
||||
|
|
@ -1340,9 +1136,10 @@ export const archiveChannel = async (serverUrl: string, channelId: string) => {
|
|||
removeCurrentUserFromChannel(serverUrl, channelId);
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on archiveChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
} finally {
|
||||
EphemeralStore.removeArchivingChannel(channelId);
|
||||
|
|
@ -1350,25 +1147,15 @@ export const archiveChannel = async (serverUrl: string, channelId: string) => {
|
|||
};
|
||||
|
||||
export const unarchiveChannel = async (serverUrl: string, channelId: string) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
EphemeralStore.addArchivingChannel(channelId);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
await client.unarchiveChannel(channelId);
|
||||
await setChannelDeleteAt(serverUrl, channelId, 0);
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on unarchiveChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
} finally {
|
||||
EphemeralStore.removeArchivingChannel(channelId);
|
||||
|
|
@ -1376,20 +1163,9 @@ export const unarchiveChannel = async (serverUrl: string, channelId: string) =>
|
|||
};
|
||||
|
||||
export const convertChannelToPrivate = async (serverUrl: string, channelId: string) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (channel) {
|
||||
EphemeralStore.addConvertingChannel(channelId);
|
||||
|
|
@ -1401,9 +1177,10 @@ export const convertChannelToPrivate = async (serverUrl: string, channelId: stri
|
|||
});
|
||||
await operator.batchRecords([channel], 'convertChannelToPrivate');
|
||||
}
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on convertChannelToPrivate', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
} finally {
|
||||
EphemeralStore.removeConvertingChannel(channelId);
|
||||
|
|
|
|||
|
|
@ -14,26 +14,29 @@ import {getChannelById} from '@queries/servers/channel';
|
|||
import {getConfig, getCurrentTeamId} from '@queries/servers/system';
|
||||
import {showAppForm} from '@screens/navigation';
|
||||
import {handleDeepLink, matchDeepLink} from '@utils/deep_link';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {tryOpenURL} from '@utils/url';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
export const executeCommand = async (serverUrl: string, intl: IntlShape, message: string, channelId: string, rootId?: string): Promise<{data?: CommandResponse; error?: string | {message: string}}> => {
|
||||
export const executeCommand = async (serverUrl: string, intl: IntlShape, message: string, channelId: string, rootId?: string): Promise<{data?: CommandResponse; error?: unknown}> => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: error as ClientErrorProps};
|
||||
return {error};
|
||||
}
|
||||
|
||||
const channel = await getChannelById(operator.database, channelId);
|
||||
const teamId = channel?.teamId || (await getCurrentTeamId(operator.database));
|
||||
const channel = await getChannelById(database, channelId);
|
||||
const teamId = channel?.teamId || (await getCurrentTeamId(database));
|
||||
|
||||
const args: CommandArgs = {
|
||||
channel_id: channelId,
|
||||
|
|
@ -68,7 +71,8 @@ export const executeCommand = async (serverUrl: string, intl: IntlShape, message
|
|||
try {
|
||||
data = await client.executeCommand(msg, args);
|
||||
} catch (error) {
|
||||
return {error: error as ClientErrorProps};
|
||||
logDebug('error on executeCommand', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
|
||||
if (data?.trigger_id) { //eslint-disable-line camelcase
|
||||
|
|
@ -89,14 +93,14 @@ const executeAppCommand = async (serverUrl: string, intl: IntlShape, parser: App
|
|||
}
|
||||
|
||||
const res = await doAppSubmit(serverUrl, creq, intl);
|
||||
if (res.error) {
|
||||
const errorResponse = res.error as AppCallResponse;
|
||||
if ('error' in res) {
|
||||
const errorResponse = res.error;
|
||||
return createErrorMessage(errorResponse.text || intl.formatMessage({
|
||||
id: 'apps.error.unknown',
|
||||
defaultMessage: 'Unknown error.',
|
||||
}));
|
||||
}
|
||||
const callResp = res.data as AppCallResponse;
|
||||
const callResp = res.data;
|
||||
|
||||
switch (callResp.type) {
|
||||
case AppCallResponseTypes.OK:
|
||||
|
|
@ -158,31 +162,22 @@ export const handleGotoLocation = async (serverUrl: string, intl: IntlShape, loc
|
|||
return {data: true};
|
||||
};
|
||||
|
||||
export const fetchCommands = async (serverUrl: string, teamId: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: error as ClientErrorProps};
|
||||
}
|
||||
export const fetchCommands = async (serverUrl: string, teamId: string): Promise<{commands: Command[]} | {error: unknown}> => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
return {commands: await client.getCommandsList(teamId)};
|
||||
} catch (error) {
|
||||
return {error: error as ClientErrorProps};
|
||||
logDebug('error on fetchCommands', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchSuggestions = async (serverUrl: string, term: string, teamId: string, channelId: string, rootId?: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: error as ClientErrorProps};
|
||||
}
|
||||
|
||||
export const fetchSuggestions = async (serverUrl: string, term: string, teamId: string, channelId: string, rootId?: string): Promise<{suggestions: AutocompleteSuggestion[]} | {error: unknown}> => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
return {suggestions: await client.getCommandAutocompleteSuggestionsList(term, teamId, channelId, rootId)};
|
||||
} catch (error) {
|
||||
return {error: error as ClientErrorProps};
|
||||
logDebug('error on fetchSuggestions', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,23 +7,14 @@ import DatabaseManager from '@database/manager';
|
|||
import {debounce} from '@helpers/api/general';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {queryCustomEmojisByName} from '@queries/servers/custom_emoji';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
export const fetchCustomEmojis = async (serverUrl: string, page = 0, perPage = General.PAGE_SIZE_DEFAULT, sort = Emoji.SORT_BY_NAME) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await client.getCustomEmojis(page, perPage, sort);
|
||||
await operator.handleCustomEmojis({
|
||||
emojis: data,
|
||||
|
|
@ -32,29 +23,20 @@ export const fetchCustomEmojis = async (serverUrl: string, page = 0, perPage = G
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchCustomEmojis', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const searchCustomEmojis = async (serverUrl: string, term: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const data = await client.searchCustomEmoji(term);
|
||||
if (data.length) {
|
||||
const names = data.map((c) => c.name);
|
||||
const exist = await queryCustomEmojisByName(operator.database, names).fetch();
|
||||
const exist = await queryCustomEmojisByName(database, names).fetch();
|
||||
const existingNames = new Set(exist.map((e) => e.name));
|
||||
const emojis = data.filter((d) => !existingNames.has(d.name));
|
||||
await operator.handleCustomEmojis({
|
||||
|
|
@ -64,31 +46,22 @@ export const searchCustomEmojis = async (serverUrl: string, term: string) => {
|
|||
}
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on searchCustomEmojis', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
const names = new Set<string>();
|
||||
const debouncedFetchEmojiByNames = debounce(async (serverUrl: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const promises: Array<Promise<CustomEmoji>> = [];
|
||||
for (const name of names) {
|
||||
promises.push(client.getCustomEmojiByName(name));
|
||||
}
|
||||
|
||||
try {
|
||||
const promises: Array<Promise<CustomEmoji>> = [];
|
||||
for (const name of names) {
|
||||
promises.push(client.getCustomEmojiByName(name));
|
||||
}
|
||||
const emojisResult = await Promise.allSettled(promises);
|
||||
const emojis = emojisResult.reduce<CustomEmoji[]>((result, e) => {
|
||||
if (e.status === 'fulfilled') {
|
||||
|
|
@ -99,8 +72,9 @@ const debouncedFetchEmojiByNames = debounce(async (serverUrl: string) => {
|
|||
if (emojis.length) {
|
||||
await operator.handleCustomEmojis({emojis, prepareRecordsOnly: false});
|
||||
}
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on debouncedFetchEmojiByNames', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}, 200, false, () => {
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ import {getConfig, getCurrentChannelId, getCurrentTeamId, getPushVerificationSta
|
|||
import {deleteMyTeams, getAvailableTeamIds, getTeamChannelHistory, queryMyTeams, queryMyTeamsByIds, queryTeamsById} from '@queries/servers/team';
|
||||
import NavigationStore from '@store/navigation_store';
|
||||
import {isDMorGM, sortChannelsByDisplayName} from '@utils/channel';
|
||||
import {getFullErrorMessage, isErrorWithStatusCode} from '@utils/errors';
|
||||
import {isTablet} from '@utils/helpers';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {processIsCRTEnabled} from '@utils/thread';
|
||||
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {Database, Model} from '@nozbe/watermelondb';
|
||||
|
||||
export type AppEntryData = {
|
||||
|
|
@ -45,7 +45,7 @@ export type AppEntryData = {
|
|||
}
|
||||
|
||||
export type AppEntryError = {
|
||||
error: Error | ClientError | string;
|
||||
error: unknown;
|
||||
}
|
||||
|
||||
export type EntryResponse = {
|
||||
|
|
@ -74,8 +74,8 @@ export const teamsToRemove = async (serverUrl: string, removeTeamIds?: string[])
|
|||
if (!operator) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
if (removeTeamIds?.length) {
|
||||
// Immediately delete myTeams so that the UI renders only teams the user is a member of.
|
||||
const removeMyTeams = await queryMyTeamsByIds(database, removeTeamIds).fetch();
|
||||
|
|
@ -95,7 +95,6 @@ export const entryRest = async (serverUrl: string, teamId?: string, channelId?:
|
|||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const lastDisconnectedAt = since || await getWebSocketLastDisconnected(database);
|
||||
|
|
@ -106,8 +105,8 @@ export const entryRest = async (serverUrl: string, teamId?: string, channelId?:
|
|||
}
|
||||
|
||||
const {initialTeamId, teamData, chData, prefData, meData, removeTeamIds, removeChannelIds, isCRTEnabled} = fetchedData;
|
||||
const chError = chData?.error as ClientError | undefined;
|
||||
if (chError?.status_code === 403) {
|
||||
const chError = chData?.error;
|
||||
if (isErrorWithStatusCode(chError) && chError.status_code === 403) {
|
||||
// if the user does not have appropriate permissions, which means the user those not belong to the team,
|
||||
// we set it as there is no errors, so that the teams and others can be properly handled
|
||||
chData!.error = undefined;
|
||||
|
|
@ -209,8 +208,8 @@ export const fetchAppEntryData = async (serverUrl: string, sinceArg: number, ini
|
|||
}
|
||||
|
||||
const inTeam = teamData.teams?.find((t) => t.id === initialTeamId);
|
||||
const chError = chData?.error as ClientError | undefined;
|
||||
if ((!inTeam && !teamData.error) || chError?.status_code === 403) {
|
||||
const chError = chData?.error;
|
||||
if ((!inTeam && !teamData.error) || (isErrorWithStatusCode(chError) && chError.status_code === 403)) {
|
||||
// User is no longer a member of the current team
|
||||
if (!removeTeamIds.includes(initialTeamId)) {
|
||||
removeTeamIds.push(initialTeamId);
|
||||
|
|
@ -254,8 +253,8 @@ export const fetchAlternateTeamData = async (
|
|||
for (const teamId of availableTeamIds) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
chData = await fetchMyChannelsForTeam(serverUrl, teamId, includeDeleted, since, fetchOnly, false, isCRTEnabled);
|
||||
const chError = chData.error as ClientError | undefined;
|
||||
if (chError?.status_code === 403) {
|
||||
const chError = chData.error;
|
||||
if (isErrorWithStatusCode(chError) && chError.status_code === 403) {
|
||||
removeTeamIds.push(teamId);
|
||||
} else {
|
||||
initialTeamId = teamId;
|
||||
|
|
@ -357,50 +356,38 @@ export async function restDeferredAppEntryActions(
|
|||
}
|
||||
|
||||
export const registerDeviceToken = async (serverUrl: string) => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
const deviceToken = await getDeviceToken();
|
||||
if (deviceToken) {
|
||||
client.attachDevice(deviceToken);
|
||||
}
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on registerDeviceToken', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
|
||||
const deviceToken = await getDeviceToken();
|
||||
if (deviceToken) {
|
||||
client.attachDevice(deviceToken);
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
};
|
||||
|
||||
export async function verifyPushProxy(serverUrl: string) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const ppVerification = await getPushVerificationStatus(database);
|
||||
if (
|
||||
ppVerification !== PUSH_PROXY_STATUS_UNKNOWN &&
|
||||
ppVerification !== ''
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const deviceId = await getDeviceToken();
|
||||
if (!deviceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const ppVerification = await getPushVerificationStatus(database);
|
||||
if (
|
||||
ppVerification !== PUSH_PROXY_STATUS_UNKNOWN &&
|
||||
ppVerification !== ''
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const response = await client.ping(deviceId);
|
||||
const canReceiveNotifications = response?.data?.CanReceiveNotifications;
|
||||
switch (canReceiveNotifications) {
|
||||
|
|
@ -412,7 +399,9 @@ export async function verifyPushProxy(serverUrl: string) {
|
|||
default:
|
||||
operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.PUSH_VERIFICATION_STATUS, value: PUSH_PROXY_STATUS_VERIFIED}], prepareRecordsOnly: false});
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (error) {
|
||||
logDebug('error on verifyPushProxy', getFullErrorMessage(error));
|
||||
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {queryAllChannels, queryAllChannelsForTeam} from '@queries/servers/channe
|
|||
import {prepareModels, truncateCrtRelatedTables} from '@queries/servers/entry';
|
||||
import {getHasCRTChanged} from '@queries/servers/preference';
|
||||
import {getConfig, getIsDataRetentionEnabled} from '@queries/servers/system';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {filterAndTransformRoles, getMemberChannelsFromGQLQuery, getMemberTeamsFromGQLQuery, gqlToClientChannelMembership, gqlToClientPreference, gqlToClientSidebarCategory, gqlToClientTeamMembership, gqlToClientUser} from '@utils/graphql';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {processIsCRTEnabled} from '@utils/thread';
|
||||
|
|
@ -24,7 +25,6 @@ import {processIsCRTEnabled} from '@utils/thread';
|
|||
import {teamsToRemove, FETCH_UNREADS_TIMEOUT, entryRest, type EntryResponse, entryInitialChannelId, restDeferredAppEntryActions, getRemoveTeamIds} from './common';
|
||||
|
||||
import type {MyChannelsRequest} from '@actions/remote/channel';
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {Database} from '@nozbe/watermelondb';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ const getChannelData = async (serverUrl: string, initialTeamId: string, userId:
|
|||
const request = exclude ? gqlOtherChannels : gqlEntryChannels;
|
||||
response = await request(serverUrl, initialTeamId);
|
||||
} catch (error) {
|
||||
return {error: (error as ClientError).message};
|
||||
return {error: getFullErrorMessage(error)};
|
||||
}
|
||||
|
||||
if ('error' in response) {
|
||||
|
|
@ -175,7 +175,7 @@ export const entryGQL = async (serverUrl: string, currentTeamId?: string, curren
|
|||
try {
|
||||
response = await gqlEntry(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: (error as ClientError).message};
|
||||
return {error: getFullErrorMessage(error)};
|
||||
}
|
||||
|
||||
if ('error' in response) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ type AfterLoginArgs = {
|
|||
serverUrl: string;
|
||||
}
|
||||
|
||||
export async function loginEntry({serverUrl}: AfterLoginArgs): Promise<{error?: any}> {
|
||||
export async function loginEntry({serverUrl}: AfterLoginArgs): Promise<{error?: unknown}> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
|
|||
|
|
@ -15,24 +15,25 @@ import {getCurrentTeamId} from '@queries/servers/system';
|
|||
import {getMyTeamById} from '@queries/servers/team';
|
||||
import {getIsCRTEnabled} from '@queries/servers/thread';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {isErrorWithStatusCode} from '@utils/errors';
|
||||
import {emitNotificationError} from '@utils/notification';
|
||||
import {setThemeDefaults, updateThemeIfNeeded} from '@utils/theme';
|
||||
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import type MyTeamModel from '@typings/database/models/servers/my_team';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
|
||||
export async function pushNotificationEntry(serverUrl: string, notification: NotificationData) {
|
||||
// We only reach this point if we have a channel Id in the notification payload
|
||||
const channelId = notification.channel_id!;
|
||||
const rootId = notification.root_id!;
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
// We only reach this point if we have a channel Id in the notification payload
|
||||
const channelId = notification.channel_id!;
|
||||
const rootId = notification.root_id!;
|
||||
const {database} = operator;
|
||||
|
||||
const currentTeamId = await getCurrentTeamId(database);
|
||||
const currentServerUrl = await DatabaseManager.getActiveServerUrl();
|
||||
|
||||
|
|
@ -65,7 +66,7 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not
|
|||
if (!myTeam) {
|
||||
const resp = await fetchMyTeam(serverUrl, teamId);
|
||||
if (resp.error) {
|
||||
if ((resp.error as ClientError).status_code === 403) {
|
||||
if (isErrorWithStatusCode(resp.error) && resp.error.status_code === 403) {
|
||||
emitNotificationError('Team');
|
||||
} else {
|
||||
emitNotificationError('Connection');
|
||||
|
|
@ -78,7 +79,7 @@ export async function pushNotificationEntry(serverUrl: string, notification: Not
|
|||
if (!myChannel) {
|
||||
const resp = await fetchMyChannel(serverUrl, teamId, channelId);
|
||||
if (resp.error) {
|
||||
if ((resp.error as ClientError).status_code === 403) {
|
||||
if (isErrorWithStatusCode(resp.error) && resp.error.status_code === 403) {
|
||||
emitNotificationError('Channel');
|
||||
} else {
|
||||
emitNotificationError('Connection');
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
import {DOWNLOAD_TIMEOUT} from '@constants/network';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {ClientResponse, ClientResponseError} from '@mattermost/react-native-network-client';
|
||||
|
||||
export const downloadFile = (serverUrl: string, fileId: string, desitnation: string) => { // Let it throw and handle it accordingly
|
||||
|
|
@ -30,29 +30,23 @@ export const uploadFile = (
|
|||
onError: (response: ClientResponseError) => void = () => {/*Do Nothing*/},
|
||||
skipBytes = 0,
|
||||
) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
return {cancel: client.uploadPostAttachment(file, channelId, onProgress, onComplete, onError, skipBytes)};
|
||||
} catch (error) {
|
||||
logDebug('uploadFile', error);
|
||||
return {error: error as ClientError};
|
||||
logDebug('error on uploadFile', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchPublicLink = async (serverUrl: string, fileId: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: error as ClientError};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const publicLink = await client!.getFilePublicLink(fileId);
|
||||
return publicLink;
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchPublicLink', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {t} from '@i18n';
|
|||
import NetworkManager from '@managers/network_manager';
|
||||
import {getDeviceToken} from '@queries/app/global';
|
||||
import {getExpandedLinks, getPushVerificationStatus} from '@queries/servers/system';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
|
@ -69,7 +70,7 @@ export const doPing = async (serverUrl: string, verifyPushProxy: boolean, timeou
|
|||
return {error: {intl: pingError}};
|
||||
}
|
||||
} catch (error) {
|
||||
logDebug('Server ping threw an exception', error);
|
||||
logDebug('Server ping threw an exception', getFullErrorMessage(error));
|
||||
NetworkManager.invalidateClient(serverUrl);
|
||||
return {error: {intl: pingError}};
|
||||
}
|
||||
|
|
@ -82,29 +83,19 @@ export const doPing = async (serverUrl: string, verifyPushProxy: boolean, timeou
|
|||
canReceiveNotifications = PUSH_PROXY_RESPONSE_VERIFIED;
|
||||
}
|
||||
|
||||
return {canReceiveNotifications, error: undefined};
|
||||
return {canReceiveNotifications};
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
};
|
||||
|
||||
export const getRedirectLocation = async (serverUrl: string, link: string) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const expandedLink = await client.getRedirectLocation(link);
|
||||
if (expandedLink?.location) {
|
||||
const storedLinks = await getExpandedLinks(operator.database);
|
||||
const storedLinks = await getExpandedLinks(database);
|
||||
storedLinks[link] = expandedLink.location;
|
||||
const expanded: IdValue = {
|
||||
id: SYSTEM_IDENTIFIERS.EXPANDED_LINKS,
|
||||
|
|
@ -118,7 +109,8 @@ export const getRedirectLocation = async (serverUrl: string, link: string) => {
|
|||
|
||||
return {expandedLink};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on getRedirectLocation', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import DatabaseManager from '@database/manager';
|
|||
import NetworkManager from '@managers/network_manager';
|
||||
import {getChannelById} from '@queries/servers/channel';
|
||||
import {getTeamById} from '@queries/servers/team';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
|
|
@ -20,7 +22,8 @@ export const fetchGroup = async (serverUrl: string, id: string, fetchOnly = fals
|
|||
// Save locally
|
||||
return operator.handleGroups({groups: [group], prepareRecordsOnly: fetchOnly});
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchGroup', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -37,7 +40,8 @@ export const fetchGroupsForAutocomplete = async (serverUrl: string, query: strin
|
|||
|
||||
return operator.handleGroups({groups: response, prepareRecordsOnly: fetchOnly});
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchGroupsForAutocomplete', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -62,7 +66,8 @@ export const fetchGroupsByNames = async (serverUrl: string, names: string[], fet
|
|||
|
||||
return operator.handleGroups({groups, prepareRecordsOnly: fetchOnly});
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchGroupsByNames', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -88,7 +93,8 @@ export const fetchGroupsForChannel = async (serverUrl: string, channelId: string
|
|||
|
||||
return {groups, groupChannels};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchGroupsForChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -115,6 +121,7 @@ export const fetchGroupsForTeam = async (serverUrl: string, teamId: string, fetc
|
|||
|
||||
return {groups, groupTeams};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchGroupsForTeam', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -141,36 +148,25 @@ export const fetchGroupsForMember = async (serverUrl: string, userId: string, fe
|
|||
|
||||
return {groups, groupMemberships};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchGroupsForMember', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchFilteredTeamGroups = async (serverUrl: string, searchTerm: string, teamId: string) => {
|
||||
try {
|
||||
const groups = await fetchGroupsForTeam(serverUrl, teamId);
|
||||
|
||||
if (groups && Array.isArray(groups)) {
|
||||
return groups.filter((g) => g.name.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
}
|
||||
|
||||
throw groups.error;
|
||||
} catch (error) {
|
||||
return {error};
|
||||
const res = await fetchGroupsForTeam(serverUrl, teamId);
|
||||
if ('error' in res) {
|
||||
return {error: res.error};
|
||||
}
|
||||
return res.groups.filter((g) => g.name.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
};
|
||||
|
||||
export const fetchFilteredChannelGroups = async (serverUrl: string, searchTerm: string, channelId: string) => {
|
||||
try {
|
||||
const groups = await fetchGroupsForChannel(serverUrl, channelId);
|
||||
|
||||
if (groups && Array.isArray(groups)) {
|
||||
return groups.filter((g) => g.name.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
}
|
||||
|
||||
throw groups.error;
|
||||
} catch (error) {
|
||||
return {error};
|
||||
const res = await fetchGroupsForChannel(serverUrl, channelId);
|
||||
if ('error' in res) {
|
||||
return {error: res.error};
|
||||
}
|
||||
return res.groups.filter((g) => g.name.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
};
|
||||
|
||||
export const fetchGroupsForTeamIfConstrained = async (serverUrl: string, teamId: string, fetchOnly = false) => {
|
||||
|
|
|
|||
|
|
@ -6,45 +6,31 @@ import DatabaseManager from '@database/manager';
|
|||
import IntegrationsMananger from '@managers/integrations_manager';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getCurrentChannelId, getCurrentTeamId} from '@queries/servers/system';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
|
||||
export const submitInteractiveDialog = async (serverUrl: string, submission: DialogSubmission) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
submission.channel_id = await getCurrentChannelId(database);
|
||||
submission.team_id = await getCurrentTeamId(database);
|
||||
|
||||
try {
|
||||
submission.channel_id = await getCurrentChannelId(database);
|
||||
submission.team_id = await getCurrentTeamId(database);
|
||||
const data = await client.submitInteractiveDialog(submission);
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on submitInteractiveDialog', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const postActionWithCookie = async (serverUrl: string, postId: string, actionId: string, actionCookie: string, selectedOption = '') => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
try {
|
||||
const data = await client.doPostActionWithCookie(postId, actionId, actionCookie, selectedOption);
|
||||
if (data?.trigger_id) {
|
||||
IntegrationsMananger.getManager(serverUrl)?.setTriggerId(data.trigger_id);
|
||||
|
|
@ -52,7 +38,8 @@ export const postActionWithCookie = async (serverUrl: string, postId: string, ac
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on postActionWithCookie', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,19 +25,15 @@ import {processPostsFetched} from '@utils/post';
|
|||
import type {Model} from '@nozbe/watermelondb';
|
||||
|
||||
const fetchNotificationData = async (serverUrl: string, notification: NotificationWithData, skipEvents = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
const channelId = notification.payload?.channel_id;
|
||||
|
||||
if (!channelId) {
|
||||
return {error: 'No chanel Id was specified'};
|
||||
}
|
||||
|
||||
try {
|
||||
const channelId = notification.payload?.channel_id;
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
if (!channelId) {
|
||||
return {error: 'No chanel Id was specified'};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
const currentTeamId = await getCurrentTeamId(database);
|
||||
let teamId = notification.payload?.team_id;
|
||||
let isDirectChannel = false;
|
||||
|
|
@ -96,7 +92,7 @@ const fetchNotificationData = async (serverUrl: string, notification: Notificati
|
|||
}
|
||||
return {};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -184,16 +180,12 @@ export const backgroundNotification = async (serverUrl: string, notification: No
|
|||
};
|
||||
|
||||
export const openNotification = async (serverUrl: string, notification: NotificationWithData) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
EphemeralStore.setNotificationTapped(true);
|
||||
|
||||
const channelId = notification.payload!.channel_id!;
|
||||
const rootId = notification.payload!.root_id!;
|
||||
try {
|
||||
EphemeralStore.setNotificationTapped(true);
|
||||
const {database} = operator;
|
||||
const channelId = notification.payload!.channel_id!;
|
||||
const rootId = notification.payload!.root_id!;
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
const isThreadNotification = isCRTEnabled && Boolean(rootId);
|
||||
|
|
@ -232,7 +224,7 @@ export const openNotification = async (serverUrl: string, notification: Notifica
|
|||
}
|
||||
return switchToChannelById(serverUrl, channelId, teamId);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
import {General} from '@constants';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
export const isNPSEnabled = async (serverUrl: string) => {
|
||||
try {
|
||||
|
|
@ -15,6 +17,7 @@ export const isNPSEnabled = async (serverUrl: string) => {
|
|||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
logDebug('error on isNPSEnabled', getFullErrorMessage(error));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
@ -25,6 +28,7 @@ export const giveFeedbackAction = async (serverUrl: string) => {
|
|||
const post = await client.npsGiveFeedbackAction();
|
||||
return {post};
|
||||
} catch (error) {
|
||||
logDebug('error on giveFeedbackAction', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,12 +9,9 @@ import {displayPermalink} from '@utils/permalink';
|
|||
import type TeamModel from '@typings/database/models/servers/team';
|
||||
|
||||
export const showPermalink = async (serverUrl: string, teamName: string, postId: string, openAsPermalink = true) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
let name = teamName;
|
||||
let team: TeamModel | undefined;
|
||||
if (!name || name === DeepLink.Redirect) {
|
||||
|
|
@ -26,7 +23,7 @@ export const showPermalink = async (serverUrl: string, teamName: string, postId:
|
|||
|
||||
await displayPermalink(name, postId, openAsPermalink);
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import {queryAllUsers} from '@queries/servers/user';
|
|||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {setFetchingThreadState} from '@store/fetching_thread_store';
|
||||
import {getValidEmojis, matchEmoticons} from '@utils/emoji/helpers';
|
||||
import {isServerError} from '@utils/errors';
|
||||
import {getFullErrorMessage, isServerError} from '@utils/errors';
|
||||
import {logDebug, logError} from '@utils/log';
|
||||
import {processPostsFetched} from '@utils/post';
|
||||
import {getPostIdsForCombinedUserActivityPost} from '@utils/post_list';
|
||||
|
|
@ -59,6 +59,7 @@ export async function createPost(serverUrl: string, post: Partial<Post>, files:
|
|||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
|
|
@ -67,8 +68,6 @@ export async function createPost(serverUrl: string, post: Partial<Post>, files:
|
|||
return {error};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const timestamp = Date.now();
|
||||
const pendingPostId = post.pending_post_id || `${currentUserId}:${timestamp}`;
|
||||
|
|
@ -135,7 +134,7 @@ export async function createPost(serverUrl: string, post: Partial<Post>, files:
|
|||
try {
|
||||
created = await client.createPost(newPost);
|
||||
} catch (error) {
|
||||
logDebug('Error sending a post', error);
|
||||
logDebug('Error sending a post', getFullErrorMessage(error));
|
||||
const errorPost = {
|
||||
...newPost,
|
||||
id: pendingPostId,
|
||||
|
|
@ -204,6 +203,7 @@ export const retryFailedPost = async (serverUrl: string, post: PostModel) => {
|
|||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
|
|
@ -212,7 +212,6 @@ export const retryFailedPost = async (serverUrl: string, post: PostModel) => {
|
|||
return {error};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
|
||||
try {
|
||||
|
|
@ -255,6 +254,7 @@ export const retryFailedPost = async (serverUrl: string, post: PostModel) => {
|
|||
}
|
||||
await operator.batchRecords(models, 'retryFailedPost - success update');
|
||||
} catch (error) {
|
||||
logDebug('error on retryFailedPost', getFullErrorMessage(error));
|
||||
if (isServerError(error) && (
|
||||
error.server_error_id === ServerErrors.DELETED_ROOT_POST_ERROR ||
|
||||
error.server_error_id === ServerErrors.TOWN_SQUARE_READ_ONLY_ERROR ||
|
||||
|
|
@ -274,7 +274,7 @@ export const retryFailedPost = async (serverUrl: string, post: PostModel) => {
|
|||
return {error};
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
};
|
||||
|
||||
export const fetchPostsForCurrentChannel = async (serverUrl: string) => {
|
||||
|
|
@ -326,7 +326,7 @@ export async function fetchPostsForChannel(serverUrl: string, channelId: string,
|
|||
|
||||
return {posts: data.posts, order: data.order, authors, actionType, previousPostId: data.previousPostId};
|
||||
} catch (error) {
|
||||
logError('FetchPostsForChannel', error);
|
||||
logDebug('error on fetchPostsForChannel', getFullErrorMessage(error));
|
||||
return {error};
|
||||
} finally {
|
||||
if (!fetchOnly) {
|
||||
|
|
@ -336,20 +336,14 @@ export async function fetchPostsForChannel(serverUrl: string, channelId: string,
|
|||
}
|
||||
|
||||
export const fetchPostsForUnreadChannels = async (serverUrl: string, channels: Channel[], memberships: ChannelMembership[], excludeChannelId?: string) => {
|
||||
try {
|
||||
const promises = [];
|
||||
for (const member of memberships) {
|
||||
const channel = channels.find((c) => c.id === member.channel_id);
|
||||
if (channel && (channel.total_msg_count - member.msg_count) > 0 && channel.id !== excludeChannelId) {
|
||||
promises.push(fetchPostsForChannel(serverUrl, channel.id));
|
||||
}
|
||||
const promises = [];
|
||||
for (const member of memberships) {
|
||||
const channel = channels.find((c) => c.id === member.channel_id);
|
||||
if (channel && (channel.total_msg_count - member.msg_count) > 0 && channel.id !== excludeChannelId) {
|
||||
promises.push(fetchPostsForChannel(serverUrl, channel.id));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
await Promise.all(promises);
|
||||
};
|
||||
|
||||
export async function fetchPosts(serverUrl: string, channelId: string, page = 0, perPage = General.POST_CHUNK_SIZE, fetchOnly = false): Promise<PostsRequest> {
|
||||
|
|
@ -357,9 +351,9 @@ export async function fetchPosts(serverUrl: string, channelId: string, page = 0,
|
|||
if (!fetchOnly) {
|
||||
EphemeralStore.addLoadingMessagesForChannel(serverUrl, channelId);
|
||||
}
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
const data = await client.getPosts(channelId, page, perPage, isCRTEnabled, isCRTEnabled);
|
||||
const result = processPostsFetched(data);
|
||||
if (!fetchOnly && result.posts.length) {
|
||||
|
|
@ -388,7 +382,8 @@ export async function fetchPosts(serverUrl: string, channelId: string, page = 0,
|
|||
}
|
||||
return result;
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchPosts', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
} finally {
|
||||
if (!fetchOnly) {
|
||||
|
|
@ -398,23 +393,13 @@ export async function fetchPosts(serverUrl: string, channelId: string, page = 0,
|
|||
}
|
||||
|
||||
export async function fetchPostsBefore(serverUrl: string, channelId: string, postId: string, perPage = General.POST_CHUNK_SIZE, fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
if (!fetchOnly) {
|
||||
EphemeralStore.addLoadingMessagesForChannel(serverUrl, channelId);
|
||||
}
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
const data = await client.getPostsBefore(channelId, postId, 0, perPage, isCRTEnabled, isCRTEnabled);
|
||||
const result = processPostsFetched(data);
|
||||
|
||||
|
|
@ -448,6 +433,7 @@ export async function fetchPostsBefore(serverUrl: string, channelId: string, pos
|
|||
}
|
||||
return result;
|
||||
} catch (error) {
|
||||
logDebug('error on fetchPostsBefore', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
return {error};
|
||||
} finally {
|
||||
|
|
@ -458,23 +444,14 @@ export async function fetchPostsBefore(serverUrl: string, channelId: string, pos
|
|||
}
|
||||
|
||||
export async function fetchPostsSince(serverUrl: string, channelId: string, since: number, fetchOnly = false): Promise<PostsRequest> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
if (!fetchOnly) {
|
||||
EphemeralStore.addLoadingMessagesForChannel(serverUrl, channelId);
|
||||
}
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
const data = await client.getPostsSince(channelId, since, isCRTEnabled, isCRTEnabled);
|
||||
const result = await processPostsFetched(data);
|
||||
if (!fetchOnly) {
|
||||
|
|
@ -503,11 +480,13 @@ export async function fetchPostsSince(serverUrl: string, channelId: string, sinc
|
|||
}
|
||||
return result;
|
||||
} catch (error) {
|
||||
logDebug('error on fetchPostsSince', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
return {error};
|
||||
} finally {
|
||||
if (!fetchOnly) {
|
||||
EphemeralStore.stopLoadingMessagesForChannel(serverUrl, channelId);
|
||||
}
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -537,7 +516,6 @@ export const fetchPostAuthors = async (serverUrl: string, posts: Post[], fetchOn
|
|||
userIdsToLoad.add(user_id);
|
||||
}
|
||||
}
|
||||
|
||||
const promises: Array<Promise<UserProfile[]>> = [];
|
||||
if (userIdsToLoad.size) {
|
||||
promises.push(client.getProfilesByIds(Array.from(userIdsToLoad)));
|
||||
|
|
@ -569,29 +547,20 @@ export const fetchPostAuthors = async (serverUrl: string, posts: Post[], fetchOn
|
|||
|
||||
return {authors: [] as UserProfile[]};
|
||||
} catch (error) {
|
||||
logError('FETCH AUTHORS ERROR', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchPostAuthors', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export async function fetchPostThread(serverUrl: string, postId: string, options?: FetchPaginatedThreadOptions, fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
setFetchingThreadState(postId, true);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
setFetchingThreadState(postId, true);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
|
||||
// Not doing any version check as server versions below 6.7 will ignore the additional params from the client.
|
||||
const data = await client.getPostThread(postId, {
|
||||
|
|
@ -630,26 +599,18 @@ export async function fetchPostThread(serverUrl: string, postId: string, options
|
|||
setFetchingThreadState(postId, false);
|
||||
return {posts: extractRecordsForTable<PostModel>(posts, MM_TABLES.SERVER.POST)};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchPostThread', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
setFetchingThreadState(postId, false);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchPostsAround(serverUrl: string, channelId: string, postId: string, perPage = General.POST_AROUND_CHUNK_SIZE, isCRTEnabled = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const [after, post, before] = await Promise.all<PostsObjectsRequest>([
|
||||
client.getPostsAfter(channelId, postId, 0, perPage, isCRTEnabled, isCRTEnabled),
|
||||
client.getPostThread(postId, {
|
||||
|
|
@ -706,27 +667,18 @@ export async function fetchPostsAround(serverUrl: string, channelId: string, pos
|
|||
|
||||
return {posts: extractRecordsForTable<PostModel>(posts, MM_TABLES.SERVER.POST)};
|
||||
} catch (error) {
|
||||
logError('FETCH POSTS AROUND ERROR', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchPostsAround', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchMissingChannelsFromPosts(serverUrl: string, posts: Post[], fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const channelIds = new Set(await queryAllMyChannel(operator.database).fetchIds());
|
||||
const channelIds = new Set(await queryAllMyChannel(database).fetchIds());
|
||||
const channelPromises: Array<Promise<Channel>> = [];
|
||||
const userPromises: Array<Promise<ChannelMembership>> = [];
|
||||
|
||||
|
|
@ -743,7 +695,7 @@ export async function fetchMissingChannelsFromPosts(serverUrl: string, posts: Po
|
|||
const channelMemberships = await Promise.all(userPromises);
|
||||
|
||||
if (!fetchOnly && channels.length && channelMemberships.length) {
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
const modelPromises = prepareMissingChannelsForAllTeams(operator, channels, channelMemberships, isCRTEnabled);
|
||||
if (modelPromises.length) {
|
||||
const channelModelsArray = await Promise.all(modelPromises);
|
||||
|
|
@ -766,25 +718,16 @@ export async function fetchMissingChannelsFromPosts(serverUrl: string, posts: Po
|
|||
channelMemberships,
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchMissingChannelsFromPosts', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchPostById(serverUrl: string, postId: string, fetchOnly = false) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const post = await client.getPost(postId);
|
||||
if (!fetchOnly) {
|
||||
const models: Model[] = [];
|
||||
|
|
@ -805,7 +748,7 @@ export async function fetchPostById(serverUrl: string, postId: string, fetchOnly
|
|||
models.push(...users);
|
||||
}
|
||||
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
if (isCRTEnabled) {
|
||||
const threadModels = await prepareThreadsFromReceivedPosts(operator, [post], false);
|
||||
if (threadModels?.length) {
|
||||
|
|
@ -818,25 +761,17 @@ export async function fetchPostById(serverUrl: string, postId: string, fetchOnly
|
|||
|
||||
return {post};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchPostById', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const togglePinPost = async (serverUrl: string, postId: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const post = await getPostById(database, postId);
|
||||
if (post) {
|
||||
const isPinned = post.isPinned;
|
||||
|
|
@ -851,25 +786,15 @@ export const togglePinPost = async (serverUrl: string, postId: string) => {
|
|||
}
|
||||
return {post};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on togglePinPost', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const deletePost = async (serverUrl: string, postToDelete: PostModel | Post) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
if (postToDelete.type === Post.POST_TYPES.COMBINED_USER_ACTIVITY && postToDelete.props?.system_post_ids) {
|
||||
const systemPostIds = getPostIdsForCombinedUserActivityPost(postToDelete.id);
|
||||
const promises = systemPostIds.map((id) => client.deletePost(id));
|
||||
|
|
@ -881,24 +806,17 @@ export const deletePost = async (serverUrl: string, postToDelete: PostModel | Po
|
|||
const post = await removePost(serverUrl, postToDelete);
|
||||
return {post};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on deletePost', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const markPostAsUnread = async (serverUrl: string, postId: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const [userId, post] = await Promise.all([getCurrentUserId(database), getPostById(database, postId)]);
|
||||
if (post && userId) {
|
||||
await client.markPostAsUnread(userId, postId);
|
||||
|
|
@ -922,33 +840,22 @@ export const markPostAsUnread = async (serverUrl: string, postId: string) => {
|
|||
|
||||
const messageCount = totalMessages - messages;
|
||||
await markChannelAsUnread(serverUrl, channelId, messageCount, mentionCount, post.createAt);
|
||||
return {
|
||||
post,
|
||||
};
|
||||
return {post};
|
||||
}
|
||||
}
|
||||
return {
|
||||
post,
|
||||
};
|
||||
return {post};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on markPostAsUnread', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const editPost = async (serverUrl: string, postId: string, postMessage: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const post = await getPostById(database, postId);
|
||||
if (post) {
|
||||
const {update_at, edit_at, message: updatedMessage} = await client.patchPost({message: postMessage, id: postId});
|
||||
|
|
@ -960,29 +867,20 @@ export const editPost = async (serverUrl: string, postId: string, postMessage: s
|
|||
});
|
||||
});
|
||||
}
|
||||
return {
|
||||
post,
|
||||
};
|
||||
return {post};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on editPost', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export async function fetchSavedPosts(serverUrl: string, teamId?: string, channelId?: string, page?: number, perPage?: number) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const userId = await getCurrentUserId(operator.database);
|
||||
const userId = await getCurrentUserId(database);
|
||||
const data = await client.getSavedPosts(userId, channelId, teamId, page, perPage);
|
||||
const posts = data.posts || {};
|
||||
const order = data.order || [];
|
||||
|
|
@ -1010,7 +908,7 @@ export async function fetchSavedPosts(serverUrl: string, teamId?: string, channe
|
|||
}
|
||||
|
||||
if (channels?.length && channelMemberships?.length) {
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
const channelPromises = prepareMissingChannelsForAllTeams(operator, channels, channelMemberships, isCRTEnabled);
|
||||
if (channelPromises.length) {
|
||||
promises.push(...channelPromises);
|
||||
|
|
@ -1027,7 +925,7 @@ export async function fetchSavedPosts(serverUrl: string, teamId?: string, channe
|
|||
}),
|
||||
);
|
||||
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
if (isCRTEnabled) {
|
||||
promises.push(prepareThreadsFromReceivedPosts(operator, postsArray, false));
|
||||
}
|
||||
|
|
@ -1047,24 +945,17 @@ export async function fetchSavedPosts(serverUrl: string, teamId?: string, channe
|
|||
posts: postsArray,
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchSavedPosts', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchPinnedPosts(serverUrl: string, channelId: string) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const data = await client.getPinnedPosts(channelId);
|
||||
const posts = data.posts || {};
|
||||
const order = data.order || [];
|
||||
|
|
@ -1078,7 +969,6 @@ export async function fetchPinnedPosts(serverUrl: string, channelId: string) {
|
|||
}
|
||||
|
||||
const promises: Array<Promise<Model[]>> = [];
|
||||
const {database} = operator;
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
|
||||
const {authors} = await fetchPostAuthors(serverUrl, postsArray, true);
|
||||
|
|
@ -1129,7 +1019,8 @@ export async function fetchPinnedPosts(serverUrl: string, channelId: string) {
|
|||
posts: postsArray,
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchPinnedPosts', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {truncateCrtRelatedTables} from '@queries/servers/entry';
|
|||
import {querySavedPostsPreferences} from '@queries/servers/preference';
|
||||
import {getCurrentUserId} from '@queries/servers/system';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {getUserIdFromChannelName} from '@utils/user';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
|
@ -22,42 +24,32 @@ export type MyPreferencesRequest = {
|
|||
};
|
||||
|
||||
export const fetchMyPreferences = async (serverUrl: string, fetchOnly = false): Promise<MyPreferencesRequest> => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const preferences = await client.getMyPreferences();
|
||||
|
||||
if (!fetchOnly) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (operator) {
|
||||
await operator.handlePreferences({
|
||||
prepareRecordsOnly: false,
|
||||
preferences,
|
||||
sync: true,
|
||||
});
|
||||
}
|
||||
await operator.handlePreferences({
|
||||
prepareRecordsOnly: false,
|
||||
preferences,
|
||||
sync: true,
|
||||
});
|
||||
}
|
||||
|
||||
return {preferences};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchMyPreferences', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const saveFavoriteChannel = async (serverUrl: string, channelId: string, isFavorite: boolean) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const userId = await getCurrentUserId(operator.database);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const userId = await getCurrentUserId(database);
|
||||
const favPref: PreferenceType = {
|
||||
category: Preferences.CATEGORIES.FAVORITE_CHANNEL,
|
||||
name: channelId,
|
||||
|
|
@ -71,13 +63,10 @@ export const saveFavoriteChannel = async (serverUrl: string, channelId: string,
|
|||
};
|
||||
|
||||
export const savePostPreference = async (serverUrl: string, postId: string) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const userId = await getCurrentUserId(operator.database);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const userId = await getCurrentUserId(database);
|
||||
const pref: PreferenceType = {
|
||||
user_id: userId,
|
||||
category: Preferences.CATEGORIES.SAVED_POST,
|
||||
|
|
@ -91,20 +80,11 @@ export const savePostPreference = async (serverUrl: string, postId: string) => {
|
|||
};
|
||||
|
||||
export const savePreference = async (serverUrl: string, preferences: PreferenceType[]) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const userId = await getCurrentUserId(operator.database);
|
||||
const userId = await getCurrentUserId(database);
|
||||
client.savePreferences(userId, preferences);
|
||||
await operator.handlePreferences({
|
||||
preferences,
|
||||
|
|
@ -113,7 +93,8 @@ export const savePreference = async (serverUrl: string, preferences: PreferenceT
|
|||
|
||||
return {preferences};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on savePreference', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -141,18 +122,15 @@ export const deleteSavedPost = async (serverUrl: string, postId: string) => {
|
|||
preference: pref,
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on deleteSavedPost', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const setDirectChannelVisible = async (serverUrl: string, channelId: string, visible = true) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (channel?.type === General.DM_CHANNEL || channel?.type === General.GM_CHANNEL) {
|
||||
const userId = await getCurrentUserId(database);
|
||||
|
|
@ -168,9 +146,9 @@ export const setDirectChannelVisible = async (serverUrl: string, channelId: stri
|
|||
return savePreference(serverUrl, [pref]);
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,30 +8,22 @@ import {getRecentPostsInChannel, getRecentPostsInThread} from '@queries/servers/
|
|||
import {queryReaction} from '@queries/servers/reaction';
|
||||
import {getCurrentChannelId, getCurrentUserId} from '@queries/servers/system';
|
||||
import {getEmojiFirstAlias} from '@utils/emoji/helpers';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type {Model} from '@nozbe/watermelondb';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
|
||||
export async function addReaction(serverUrl: string, postId: string, emojiName: string) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const emojiAlias = getEmojiFirstAlias(emojiName);
|
||||
const reacted = await queryReaction(operator.database, emojiAlias, postId, currentUserId).fetchCount() > 0;
|
||||
const reacted = await queryReaction(database, emojiAlias, postId, currentUserId).fetchCount() > 0;
|
||||
if (!reacted) {
|
||||
const reaction = await client.addReaction(currentUserId, postId, emojiAlias);
|
||||
const models: Model[] = [];
|
||||
|
|
@ -64,25 +56,17 @@ export async function addReaction(serverUrl: string, postId: string, emojiName:
|
|||
} as Reaction,
|
||||
};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on addReaction', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const removeReaction = async (serverUrl: string, postId: string, emojiName: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const emojiAlias = getEmojiFirstAlias(emojiName);
|
||||
await client.removeReaction(currentUserId, postId, emojiAlias);
|
||||
|
|
@ -98,24 +82,21 @@ export const removeReaction = async (serverUrl: string, postId: string, emojiNam
|
|||
|
||||
return {reaction};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on removeReaction', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const handleReactionToLatestPost = async (serverUrl: string, emojiName: string, add: boolean, rootId?: string) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
let posts: PostModel[];
|
||||
if (rootId) {
|
||||
posts = await getRecentPostsInThread(operator.database, rootId);
|
||||
posts = await getRecentPostsInThread(database, rootId);
|
||||
} else {
|
||||
const channelId = await getCurrentChannelId(operator.database);
|
||||
posts = await getRecentPostsInChannel(operator.database, channelId);
|
||||
const channelId = await getCurrentChannelId(database);
|
||||
posts = await getRecentPostsInChannel(database, channelId);
|
||||
}
|
||||
|
||||
if (add) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ export async function retryInitialTeamAndChannel(serverUrl: string) {
|
|||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
try {
|
||||
|
|
@ -139,7 +138,6 @@ export async function retryInitialChannel(serverUrl: string, teamId: string) {
|
|||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
import DatabaseManager from '@database/manager';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {queryRoles} from '@queries/servers/role';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
|
|
@ -17,43 +19,29 @@ export const fetchRolesIfNeeded = async (serverUrl: string, updatedRoles: string
|
|||
return {roles: []};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
let database;
|
||||
let operator;
|
||||
try {
|
||||
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
database = result.database;
|
||||
operator = result.operator;
|
||||
} catch (e) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
let newRoles;
|
||||
if (force) {
|
||||
newRoles = updatedRoles;
|
||||
} else {
|
||||
const existingRoles = await queryRoles(database).fetch();
|
||||
|
||||
let newRoles;
|
||||
if (force) {
|
||||
newRoles = updatedRoles;
|
||||
} else {
|
||||
const existingRoles = await queryRoles(database).fetch();
|
||||
const roleNames = new Set(existingRoles.map((role) => {
|
||||
return role.name;
|
||||
}));
|
||||
|
||||
const roleNames = new Set(existingRoles.map((role) => {
|
||||
return role.name;
|
||||
}));
|
||||
newRoles = updatedRoles.filter((newRole) => {
|
||||
return !roleNames.has(newRole);
|
||||
});
|
||||
}
|
||||
|
||||
newRoles = updatedRoles.filter((newRole) => {
|
||||
return !roleNames.has(newRole);
|
||||
});
|
||||
}
|
||||
if (!newRoles.length) {
|
||||
return {roles: []};
|
||||
}
|
||||
|
||||
if (!newRoles.length) {
|
||||
return {roles: []};
|
||||
}
|
||||
|
||||
try {
|
||||
const roles = await client.getRolesByNames(newRoles);
|
||||
if (!fetchOnly) {
|
||||
await operator.handleRole({
|
||||
|
|
@ -64,7 +52,8 @@ export const fetchRolesIfNeeded = async (serverUrl: string, updatedRoles: string
|
|||
|
||||
return {roles};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchRolesIfNeeded', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import NetworkManager from '@managers/network_manager';
|
|||
import {prepareMissingChannelsForAllTeams} from '@queries/servers/channel';
|
||||
import {getIsCRTEnabled, prepareThreadsFromReceivedPosts} from '@queries/servers/thread';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import {logError} from '@utils/log';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {fetchPostAuthors, fetchMissingChannelsFromPosts} from './post';
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
|
@ -48,7 +49,7 @@ export async function fetchRecentMentions(serverUrl: string): Promise<PostSearch
|
|||
|
||||
export const searchPosts = async (serverUrl: string, teamId: string, params: PostSearchParams): Promise<PostSearchRequest> => {
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
let postsArray: Post[] = [];
|
||||
|
|
@ -60,7 +61,7 @@ export const searchPosts = async (serverUrl: string, teamId: string, params: Pos
|
|||
const promises: Array<Promise<Model[]>> = [];
|
||||
postsArray = order.map((id) => posts[id]);
|
||||
if (postsArray.length) {
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
if (isCRTEnabled) {
|
||||
promises.push(prepareThreadsFromReceivedPosts(operator, postsArray, false));
|
||||
}
|
||||
|
|
@ -109,8 +110,8 @@ export const searchPosts = async (serverUrl: string, teamId: string, params: Pos
|
|||
posts: postsArray,
|
||||
};
|
||||
} catch (error) {
|
||||
logError('Failed: searchPosts', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on searchPosts', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -129,7 +130,8 @@ export const searchFiles = async (serverUrl: string, teamId: string, params: Fil
|
|||
const channels = [...new Set(allChannelIds)];
|
||||
return {files, channels};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on searchFiles', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ import {getServerDisplayName} from '@queries/app/servers';
|
|||
import {getCurrentUserId, getExpiredSession} from '@queries/servers/system';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {getFullErrorMessage, isErrorWithStatusCode, isErrorWithUrl} from '@utils/errors';
|
||||
import {logWarning, logError, logDebug} from '@utils/log';
|
||||
import {scheduleExpiredNotification} from '@utils/notification';
|
||||
import {getCSRFFromCookie} from '@utils/security';
|
||||
|
||||
import {loginEntry} from './entry';
|
||||
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {LoginArgs} from '@typings/database/database';
|
||||
|
||||
const HTTP_UNAUTHORIZED = 401;
|
||||
|
|
@ -44,7 +44,7 @@ export const addPushProxyVerificationStateFromLogin = async (serverUrl: string)
|
|||
logDebug('error setting the push proxy verification state on login', error);
|
||||
}
|
||||
};
|
||||
export const forceLogoutIfNecessary = async (serverUrl: string, err: ClientErrorProps) => {
|
||||
export const forceLogoutIfNecessary = async (serverUrl: string, err: unknown) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
@ -52,7 +52,7 @@ export const forceLogoutIfNecessary = async (serverUrl: string, err: ClientError
|
|||
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
|
||||
if ('status_code' in err && err.status_code === HTTP_UNAUTHORIZED && err?.url?.indexOf('/login') === -1 && currentUserId) {
|
||||
if (isErrorWithStatusCode(err) && err.status_code === HTTP_UNAUTHORIZED && isErrorWithUrl(err) && err.url?.indexOf('/login') === -1 && currentUserId) {
|
||||
await logout(serverUrl);
|
||||
}
|
||||
|
||||
|
|
@ -69,9 +69,9 @@ export const fetchSessions = async (serverUrl: string, currentUserId: string) =>
|
|||
|
||||
try {
|
||||
return await client.getSessions(currentUserId);
|
||||
} catch (e) {
|
||||
logError('fetchSessions', e);
|
||||
await forceLogoutIfNecessary(serverUrl, e as ClientError);
|
||||
} catch (error) {
|
||||
logDebug('error on fetchSessions', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
|
@ -86,14 +86,8 @@ export const login = async (serverUrl: string, {ldapOnly = false, loginId, mfaTo
|
|||
return {error: 'App database not found.', failed: true};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: error as Error, failed: true};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
deviceToken = await getDeviceToken();
|
||||
user = await client.login(
|
||||
loginId,
|
||||
|
|
@ -123,16 +117,17 @@ export const login = async (serverUrl: string, {ldapOnly = false, loginId, mfaTo
|
|||
const csrfToken = await getCSRFFromCookie(serverUrl);
|
||||
client.setCSRFToken(csrfToken);
|
||||
} catch (error) {
|
||||
return {error: error as Error, failed: true};
|
||||
logDebug('error on login', getFullErrorMessage(error));
|
||||
return {error, failed: true};
|
||||
}
|
||||
|
||||
try {
|
||||
await addPushProxyVerificationStateFromLogin(serverUrl);
|
||||
const {error} = await loginEntry({serverUrl});
|
||||
await DatabaseManager.setActiveServerDatabase(serverUrl);
|
||||
return {error: error as ClientError, failed: false};
|
||||
return {error, failed: false};
|
||||
} catch (error) {
|
||||
return {error: error as ClientError, failed: false};
|
||||
return {error, failed: false};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -143,7 +138,7 @@ export const logout = async (serverUrl: string, skipServerLogout = false, remove
|
|||
await client.logout();
|
||||
} catch (error) {
|
||||
// We want to log the user even if logging out from the server failed
|
||||
logWarning('An error occurred logging out from the server', serverUrl, error);
|
||||
logWarning('An error occurred logging out from the server', serverUrl, getFullErrorMessage(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,50 +198,34 @@ export const scheduleSessionNotification = async (serverUrl: string) => {
|
|||
}
|
||||
} catch (e) {
|
||||
logError('scheduleExpiredNotification', e);
|
||||
await forceLogoutIfNecessary(serverUrl, e as ClientError);
|
||||
await forceLogoutIfNecessary(serverUrl, e);
|
||||
}
|
||||
};
|
||||
|
||||
export const sendPasswordResetEmail = async (serverUrl: string, email: string) => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const response = await client.sendPasswordResetEmail(email);
|
||||
return {status: response.status};
|
||||
} catch (error) {
|
||||
logDebug('error on sendPasswordResetEmail', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await client.sendPasswordResetEmail(email);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
return {
|
||||
status: response.status,
|
||||
error: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
export const ssoLogin = async (serverUrl: string, serverDisplayName: string, serverIdentifier: string, bearerToken: string, csrfToken: string): Promise<LoginActionResponse> => {
|
||||
let user;
|
||||
|
||||
const database = DatabaseManager.appDatabase?.database;
|
||||
if (!database) {
|
||||
return {error: 'App database not found', failed: true};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: error as Error, failed: true};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
client.setBearerToken(bearerToken);
|
||||
client.setCSRFToken(csrfToken);
|
||||
client.setBearerToken(bearerToken);
|
||||
client.setCSRFToken(csrfToken);
|
||||
|
||||
// Setting up active database for this SSO login flow
|
||||
try {
|
||||
// Setting up active database for this SSO login flow
|
||||
const server = await DatabaseManager.createServerDatabase({
|
||||
config: {
|
||||
dbName: serverUrl,
|
||||
|
|
@ -255,7 +234,7 @@ export const ssoLogin = async (serverUrl: string, serverDisplayName: string, ser
|
|||
displayName: serverDisplayName,
|
||||
},
|
||||
});
|
||||
user = await client.getMe();
|
||||
const user = await client.getMe();
|
||||
await server?.operator.handleUsers({users: [user], prepareRecordsOnly: false});
|
||||
await server?.operator.handleSystem({
|
||||
systems: [{
|
||||
|
|
@ -264,17 +243,18 @@ export const ssoLogin = async (serverUrl: string, serverDisplayName: string, ser
|
|||
}],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
} catch (e) {
|
||||
return {error: e as ClientError, failed: true};
|
||||
} catch (error) {
|
||||
logDebug('error on ssoLogin', getFullErrorMessage(error));
|
||||
return {error, failed: true};
|
||||
}
|
||||
|
||||
try {
|
||||
await addPushProxyVerificationStateFromLogin(serverUrl);
|
||||
const {error} = await loginEntry({serverUrl});
|
||||
await DatabaseManager.setActiveServerDatabase(serverUrl);
|
||||
return {error: error as ClientError, failed: false};
|
||||
return {error, failed: false};
|
||||
} catch (error) {
|
||||
return {error: error as ClientError, failed: false};
|
||||
return {error, failed: false};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import {forceLogoutIfNecessary} from '@actions/remote/session';
|
|||
import DatabaseManager from '@database/manager';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getCurrentUserId} from '@queries/servers/system';
|
||||
|
||||
import type ClientError from '@client/rest/error';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
export type ConfigAndLicenseRequest = {
|
||||
config?: ClientConfig;
|
||||
|
|
@ -23,51 +23,36 @@ export type DataRetentionPoliciesRequest = {
|
|||
}
|
||||
|
||||
export const fetchDataRetentionPolicy = async (serverUrl: string, fetchOnly = false): Promise<DataRetentionPoliciesRequest> => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {data: globalPolicy, error: globalPolicyError} = await fetchGlobalDataRetentionPolicy(serverUrl);
|
||||
const {data: teamPolicies, error: teamPoliciesError} = await fetchAllGranularDataRetentionPolicies(serverUrl);
|
||||
const {data: channelPolicies, error: channelPoliciesError} = await fetchAllGranularDataRetentionPolicies(serverUrl, true);
|
||||
|
||||
try {
|
||||
const {data: globalPolicy, error: globalPolicyError} = await fetchGlobalDataRetentionPolicy(serverUrl);
|
||||
const {data: teamPolicies, error: teamPoliciesError} = await fetchAllGranularDataRetentionPolicies(serverUrl);
|
||||
const {data: channelPolicies, error: channelPoliciesError} = await fetchAllGranularDataRetentionPolicies(serverUrl, true);
|
||||
|
||||
const hasError = globalPolicyError || teamPoliciesError || channelPoliciesError;
|
||||
if (hasError) {
|
||||
return hasError;
|
||||
}
|
||||
|
||||
const data = {
|
||||
globalPolicy,
|
||||
teamPolicies: teamPolicies as TeamDataRetentionPolicy[],
|
||||
channelPolicies: channelPolicies as ChannelDataRetentionPolicy[],
|
||||
};
|
||||
|
||||
if (!fetchOnly) {
|
||||
await storeDataRetentionPolicies(serverUrl, data);
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
const error = globalPolicyError || teamPoliciesError || channelPoliciesError;
|
||||
if (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
const data = {
|
||||
globalPolicy,
|
||||
teamPolicies: teamPolicies as TeamDataRetentionPolicy[],
|
||||
channelPolicies: channelPolicies as ChannelDataRetentionPolicy[],
|
||||
};
|
||||
|
||||
if (!fetchOnly) {
|
||||
await storeDataRetentionPolicies(serverUrl, data);
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const fetchGlobalDataRetentionPolicy = async (serverUrl: string): Promise<{data?: GlobalDataRetentionPolicy; error?: unknown}> => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const data = await client.getGlobalDataRetentionPolicy();
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchGlobalDataRetentionPolicy', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -78,43 +63,31 @@ export const fetchAllGranularDataRetentionPolicies = async (
|
|||
page = 0,
|
||||
policies: Array<TeamDataRetentionPolicy | ChannelDataRetentionPolicy> = [],
|
||||
): Promise<{data?: Array<TeamDataRetentionPolicy | ChannelDataRetentionPolicy>; error?: unknown}> => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
let data;
|
||||
if (isChannel) {
|
||||
data = await client.getChannelDataRetentionPolicies(currentUserId, page);
|
||||
} else {
|
||||
data = await client.getTeamDataRetentionPolicies(currentUserId, page);
|
||||
}
|
||||
policies.push(...data.policies);
|
||||
if (policies.length < data.total_count) {
|
||||
await fetchAllGranularDataRetentionPolicies(serverUrl, isChannel, page + 1, policies);
|
||||
}
|
||||
return {data: policies};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchAllGranularDataRetentionPolicies', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
let data;
|
||||
if (isChannel) {
|
||||
data = await client.getChannelDataRetentionPolicies(currentUserId, page);
|
||||
} else {
|
||||
data = await client.getTeamDataRetentionPolicies(currentUserId, page);
|
||||
}
|
||||
policies.push(...data.policies);
|
||||
if (policies.length < data.total_count) {
|
||||
await fetchAllGranularDataRetentionPolicies(serverUrl, isChannel, page + 1, policies);
|
||||
}
|
||||
return {data: policies};
|
||||
};
|
||||
|
||||
export const fetchConfigAndLicense = async (serverUrl: string, fetchOnly = false): Promise<ConfigAndLicenseRequest> => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const [config, license]: [ClientConfig, ClientLicense] = await Promise.all([
|
||||
client.getClientConfigOld(),
|
||||
client.getClientLicenseOld(),
|
||||
|
|
@ -126,7 +99,8 @@ export const fetchConfigAndLicense = async (serverUrl: string, fetchOnly = false
|
|||
|
||||
return {config, license};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchConfigAndLicense', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {addTeamToTeamHistory, prepareDeleteTeam, prepareMyTeams, getNthLastChann
|
|||
import {dismissAllModalsAndPopToRoot} from '@screens/navigation';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {setTeamLoading} from '@store/team_load_store';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {isTablet} from '@utils/helpers';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
|
|
@ -26,7 +27,6 @@ import {fetchRolesIfNeeded} from './role';
|
|||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {Model} from '@nozbe/watermelondb';
|
||||
|
||||
export type MyTeamsRequest = {
|
||||
|
|
@ -52,15 +52,11 @@ export async function addCurrentUserToTeam(serverUrl: string, teamId: string, fe
|
|||
}
|
||||
|
||||
export async function addUserToTeam(serverUrl: string, teamId: string, userId: string, fetchOnly = false) {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
let loadEventSent = false;
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
EphemeralStore.startAddingToTeam(teamId);
|
||||
const team = await client.getTeam(teamId);
|
||||
const member = await client.addToTeam(teamId, userId);
|
||||
|
|
@ -71,45 +67,40 @@ export async function addUserToTeam(serverUrl: string, teamId: string, userId: s
|
|||
|
||||
fetchRolesIfNeeded(serverUrl, member.roles.split(' '));
|
||||
const {channels, memberships: channelMembers, categories} = await fetchMyChannelsForTeam(serverUrl, teamId, false, 0, true);
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (operator) {
|
||||
const myTeams: MyTeam[] = [{
|
||||
id: member.team_id,
|
||||
roles: member.roles,
|
||||
}];
|
||||
const myTeams: MyTeam[] = [{
|
||||
id: member.team_id,
|
||||
roles: member.roles,
|
||||
}];
|
||||
|
||||
const models: Model[] = (await Promise.all([
|
||||
operator.handleTeam({teams: [team], prepareRecordsOnly: true}),
|
||||
operator.handleMyTeam({myTeams, prepareRecordsOnly: true}),
|
||||
operator.handleTeamMemberships({teamMemberships: [member], prepareRecordsOnly: true}),
|
||||
...await prepareMyChannelsForTeam(operator, teamId, channels || [], channelMembers || []),
|
||||
prepareCategoriesAndCategoriesChannels(operator, categories || [], true),
|
||||
])).flat();
|
||||
const models: Model[] = (await Promise.all([
|
||||
operator.handleTeam({teams: [team], prepareRecordsOnly: true}),
|
||||
operator.handleMyTeam({myTeams, prepareRecordsOnly: true}),
|
||||
operator.handleTeamMemberships({teamMemberships: [member], prepareRecordsOnly: true}),
|
||||
...await prepareMyChannelsForTeam(operator, teamId, channels || [], channelMembers || []),
|
||||
prepareCategoriesAndCategoriesChannels(operator, categories || [], true),
|
||||
])).flat();
|
||||
|
||||
await operator.batchRecords(models, 'addUserToTeam');
|
||||
setTeamLoading(serverUrl, false);
|
||||
loadEventSent = false;
|
||||
await operator.batchRecords(models, 'addUserToTeam');
|
||||
setTeamLoading(serverUrl, false);
|
||||
loadEventSent = false;
|
||||
|
||||
if (await isTablet()) {
|
||||
const channel = await getDefaultChannelForTeam(operator.database, teamId);
|
||||
if (channel) {
|
||||
fetchPostsForChannel(serverUrl, channel.id);
|
||||
}
|
||||
if (await isTablet()) {
|
||||
const channel = await getDefaultChannelForTeam(database, teamId);
|
||||
if (channel) {
|
||||
fetchPostsForChannel(serverUrl, channel.id);
|
||||
}
|
||||
} else {
|
||||
setTeamLoading(serverUrl, false);
|
||||
loadEventSent = false;
|
||||
}
|
||||
}
|
||||
EphemeralStore.finishAddingToTeam(teamId);
|
||||
updateCanJoinTeams(serverUrl);
|
||||
return {member};
|
||||
} catch (error) {
|
||||
logDebug('error on addUserToTeam', getFullErrorMessage(error));
|
||||
if (loadEventSent) {
|
||||
setTeamLoading(serverUrl, false);
|
||||
}
|
||||
EphemeralStore.finishAddingToTeam(teamId);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -141,11 +132,12 @@ export async function addUsersToTeam(serverUrl: string, teamId: string, userIds:
|
|||
EphemeralStore.finishAddingToTeam(teamId);
|
||||
return {members};
|
||||
} catch (error) {
|
||||
logDebug('error on addUsersToTeam', getFullErrorMessage(error));
|
||||
if (EphemeralStore.isAddingToTeam(teamId)) {
|
||||
EphemeralStore.finishAddingToTeam(teamId);
|
||||
}
|
||||
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -157,27 +149,23 @@ export async function sendEmailInvitesToTeam(serverUrl: string, teamId: string,
|
|||
|
||||
return {members};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on sendEmailInvitesToTeam', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchMyTeams(serverUrl: string, fetchOnly = false): Promise<MyTeamsRequest> {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const [teams, memberships]: [Team[], TeamMembership[]] = await Promise.all([
|
||||
client.getMyTeams(),
|
||||
client.getMyTeamMembers(),
|
||||
]);
|
||||
|
||||
if (!fetchOnly) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
const modelPromises: Array<Promise<Model[]>> = [];
|
||||
if (operator) {
|
||||
const removeTeamIds = new Set(memberships.filter((m) => m.delete_at > 0).map((m) => m.team_id));
|
||||
|
|
@ -189,7 +177,7 @@ export async function fetchMyTeams(serverUrl: string, fetchOnly = false): Promis
|
|||
|
||||
if (removeTeamIds.size) {
|
||||
// Immediately delete myTeams so that the UI renders only teams the user is a member of.
|
||||
const removeTeams = await queryTeamsById(operator.database, Array.from(removeTeamIds)).fetch();
|
||||
const removeTeams = await queryTeamsById(database, Array.from(removeTeamIds)).fetch();
|
||||
removeTeams.forEach((team) => {
|
||||
modelPromises.push(prepareDeleteTeam(team));
|
||||
});
|
||||
|
|
@ -207,41 +195,36 @@ export async function fetchMyTeams(serverUrl: string, fetchOnly = false): Promis
|
|||
|
||||
return {teams, memberships};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchMyTeams', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchMyTeam(serverUrl: string, teamId: string, fetchOnly = false): Promise<MyTeamsRequest> {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const [team, membership] = await Promise.all([
|
||||
client.getTeam(teamId),
|
||||
client.getTeamMember(teamId, 'me'),
|
||||
]);
|
||||
if (!fetchOnly) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (operator) {
|
||||
const modelPromises = prepareMyTeams(operator, [team], [membership]);
|
||||
if (modelPromises.length) {
|
||||
const models = await Promise.all(modelPromises);
|
||||
const flattenedModels = models.flat();
|
||||
if (flattenedModels?.length > 0) {
|
||||
await operator.batchRecords(flattenedModels, 'fetchMyTeam');
|
||||
}
|
||||
const modelPromises = prepareMyTeams(operator, [team], [membership]);
|
||||
if (modelPromises.length) {
|
||||
const models = await Promise.all(modelPromises);
|
||||
const flattenedModels = models.flat();
|
||||
if (flattenedModels?.length > 0) {
|
||||
await operator.batchRecords(flattenedModels, 'fetchMyTeam');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {teams: [team], memberships: [membership]};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchMyTeam', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -252,7 +235,8 @@ export const fetchAllTeams = async (serverUrl: string, page = 0, perPage = PER_P
|
|||
const teams = await client.getTeams(page, perPage);
|
||||
return {teams};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchAllTeams', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -321,8 +305,9 @@ export const updateCanJoinTeams = async (serverUrl: string) => {
|
|||
EphemeralStore.setCanJoinOtherTeams(serverUrl, canJoin);
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on updateCanJoinTeams', getFullErrorMessage(error));
|
||||
EphemeralStore.setCanJoinOtherTeams(serverUrl, false);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -344,31 +329,25 @@ export const fetchTeamsChannelsAndUnreadPosts = async (serverUrl: string, since:
|
|||
}
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
};
|
||||
|
||||
export async function fetchTeamByName(serverUrl: string, teamName: string, fetchOnly = false) {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const team = await client.getTeamByName(teamName);
|
||||
|
||||
if (!fetchOnly) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (operator) {
|
||||
const models = await operator.handleTeam({teams: [team], prepareRecordsOnly: true});
|
||||
await operator.batchRecords(models, 'fetchTeamByName');
|
||||
}
|
||||
const models = await operator.handleTeam({teams: [team], prepareRecordsOnly: true});
|
||||
await operator.batchRecords(models, 'fetchTeamByName');
|
||||
}
|
||||
|
||||
return {team};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchTeamByName', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -384,14 +363,8 @@ export const removeCurrentUserFromTeam = async (serverUrl: string, teamId: strin
|
|||
};
|
||||
|
||||
export const removeUserFromTeam = async (serverUrl: string, teamId: string, userId: string, fetchOnly = false) => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
await client.removeFromTeam(teamId, userId);
|
||||
|
||||
if (!fetchOnly) {
|
||||
|
|
@ -399,9 +372,10 @@ export const removeUserFromTeam = async (serverUrl: string, teamId: string, user
|
|||
updateCanJoinTeams(serverUrl);
|
||||
}
|
||||
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on removeUserFromTeam', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -411,8 +385,8 @@ export async function handleTeamChange(serverUrl: string, teamId: string) {
|
|||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
const currentTeamId = await getCurrentTeamId(database);
|
||||
|
||||
if (currentTeamId === teamId) {
|
||||
|
|
@ -496,7 +470,8 @@ export async function getTeamMembersByIds(serverUrl: string, teamId: string, use
|
|||
|
||||
return {members};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on getTeamMembersByIds', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,24 +4,19 @@
|
|||
import DatabaseManager from '@database/manager';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
import type ClientError from '@client/rest/error';
|
||||
|
||||
export async function fetchTermsOfService(serverUrl: string): Promise<{terms?: TermsOfService; error?: any}> {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const terms = await client.getTermsOfService();
|
||||
return {terms};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchTermsOfService', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +42,8 @@ export async function updateTermsOfServiceStatus(serverUrl: string, id: string,
|
|||
}
|
||||
return {resp};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on updateTermsOfServiceStatus', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {getPostById} from '@queries/servers/post';
|
|||
import {getConfigValue, getCurrentChannelId, getCurrentTeamId} from '@queries/servers/system';
|
||||
import {getIsCRTEnabled, getThreadById, getTeamThreadsSyncData} from '@queries/servers/thread';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {showThreadFollowingSnackbar} from '@utils/snack_bar';
|
||||
import {getThreadsListEdges} from '@utils/thread';
|
||||
|
||||
|
|
@ -76,34 +78,23 @@ export const fetchAndSwitchToThread = async (serverUrl: string, rootId: string,
|
|||
};
|
||||
|
||||
export const fetchThread = async (serverUrl: string, teamId: string, threadId: string, extended?: boolean) => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const thread = await client.getThread('me', teamId, threadId, extended);
|
||||
|
||||
await processReceivedThreads(serverUrl, [thread], teamId);
|
||||
|
||||
return {data: thread};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchThread', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const updateTeamThreadsAsRead = async (serverUrl: string, teamId: string) => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const data = await client.updateTeamThreadsAsRead('me', teamId);
|
||||
|
||||
// Update locally
|
||||
|
|
@ -111,26 +102,17 @@ export const updateTeamThreadsAsRead = async (serverUrl: string, teamId: string)
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on updateTeamThreadsAsRead', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const markThreadAsRead = async (serverUrl: string, teamId: string | undefined, threadId: string, updateLastViewed = true) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const timestamp = Date.now();
|
||||
|
||||
// DM/GM doesn't have a teamId, so we pass the current team id
|
||||
|
|
@ -159,26 +141,17 @@ export const markThreadAsRead = async (serverUrl: string, teamId: string | undef
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on markThreadAsRead', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const markThreadAsUnread = async (serverUrl: string, teamId: string, threadId: string, postId: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
// DM/GM doesn't have a teamId, so we pass the current team id
|
||||
let threadTeamId = teamId;
|
||||
if (!threadTeamId) {
|
||||
|
|
@ -198,32 +171,23 @@ export const markThreadAsUnread = async (serverUrl: string, teamId: string, thre
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on markThreadAsUnread', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const updateThreadFollowing = async (serverUrl: string, teamId: string, threadId: string, state: boolean, showSnackBar: boolean) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
// DM/GM doesn't have a teamId, so we pass the current team id
|
||||
let threadTeamId = teamId;
|
||||
if (!threadTeamId) {
|
||||
threadTeamId = await getCurrentTeamId(database);
|
||||
}
|
||||
// DM/GM doesn't have a teamId, so we pass the current team id
|
||||
let threadTeamId = teamId;
|
||||
if (!threadTeamId) {
|
||||
threadTeamId = await getCurrentTeamId(database);
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await client.updateThreadFollow('me', threadTeamId, threadId, state);
|
||||
|
||||
// Update locally
|
||||
|
|
@ -236,7 +200,8 @@ export const updateThreadFollowing = async (serverUrl: string, teamId: string, t
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on updateThreadFollowing', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -249,10 +214,10 @@ export const fetchThreads = async (
|
|||
pages?: number,
|
||||
) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
|
|
@ -263,12 +228,12 @@ export const fetchThreads = async (
|
|||
|
||||
const fetchDirection = direction ?? Direction.Up;
|
||||
|
||||
const currentUser = await getCurrentUser(operator.database);
|
||||
const currentUser = await getCurrentUser(database);
|
||||
if (!currentUser) {
|
||||
return {error: 'currentUser not found'};
|
||||
}
|
||||
|
||||
const version = await getConfigValue(operator.database, 'Version');
|
||||
const version = await getConfigValue(database, 'Version');
|
||||
const threadsData: Thread[] = [];
|
||||
|
||||
let currentPage = 0;
|
||||
|
|
@ -302,6 +267,7 @@ export const fetchThreads = async (
|
|||
try {
|
||||
await fetchThreadsFunc(options);
|
||||
} catch (error) {
|
||||
logDebug('error on fetchThreads', getFullErrorMessage(error));
|
||||
if (__DEV__) {
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -312,13 +278,9 @@ export const fetchThreads = async (
|
|||
};
|
||||
|
||||
export const syncTeamThreads = async (serverUrl: string, teamId: string, prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const syncData = await getTeamThreadsSyncData(operator.database, teamId);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const syncData = await getTeamThreadsSyncData(database, teamId);
|
||||
const syncDataUpdate = {
|
||||
id: teamId,
|
||||
} as TeamThreadsSync;
|
||||
|
|
@ -418,12 +380,9 @@ export const syncTeamThreads = async (serverUrl: string, teamId: string, prepare
|
|||
};
|
||||
|
||||
export const loadEarlierThreads = async (serverUrl: string, teamId: string, lastThreadId: string, prepareRecordsOnly = false) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
/*
|
||||
* - We will fetch one page of old threads
|
||||
* - Update the sync data with the earliest thread last_reply_at timestamp
|
||||
|
|
@ -476,7 +435,7 @@ export const loadEarlierThreads = async (serverUrl: string, teamId: string, last
|
|||
}
|
||||
}
|
||||
|
||||
return {error: false, models, threads};
|
||||
return {models, threads};
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,15 +16,14 @@ import {getMembersCountByChannelsId, queryChannelsByTypes} from '@queries/server
|
|||
import {queryGroupsByNames} from '@queries/servers/group';
|
||||
import {getConfig, getCurrentUserId} from '@queries/servers/system';
|
||||
import {getCurrentUser, prepareUsers, queryAllUsers, queryUsersById, queryUsersByIdsOrUsernames, queryUsersByUsername} from '@queries/servers/user';
|
||||
import {logError} from '@utils/log';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {getDeviceTimezone, isTimezoneEnabled} from '@utils/timezone';
|
||||
import {getUserTimezoneProps, removeUserFromList} from '@utils/user';
|
||||
|
||||
import {fetchGroupsByNames} from './groups';
|
||||
import {forceLogoutIfNecessary} from './session';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {Model} from '@nozbe/watermelondb';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
|
|
@ -45,14 +44,10 @@ export type ProfilesInChannelRequest = {
|
|||
}
|
||||
|
||||
export const fetchMe = async (serverUrl: string, fetchOnly = false): Promise<MyUserRequest> => {
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const [user, userStatus] = await Promise.all<[Promise<UserProfile>, Promise<UserStatus>]>([
|
||||
client.getMe(),
|
||||
client.getStatus('me'),
|
||||
|
|
@ -61,34 +56,27 @@ export const fetchMe = async (serverUrl: string, fetchOnly = false): Promise<MyU
|
|||
user.status = userStatus.status;
|
||||
|
||||
if (!fetchOnly) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (operator) {
|
||||
await operator.handleUsers({users: [user], prepareRecordsOnly: false});
|
||||
}
|
||||
await operator.handleUsers({users: [user], prepareRecordsOnly: false});
|
||||
}
|
||||
|
||||
return {user};
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on fetchMe', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export async function fetchProfilesInChannel(serverUrl: string, channelId: string, excludeUserId?: string, options?: GetUsersOptions, fetchOnly = false): Promise<ProfilesInChannelRequest> {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {channelId, error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const users = await client.getProfilesInChannel(channelId, options);
|
||||
const uniqueUsers = Array.from(new Set(users));
|
||||
const filteredUsers = uniqueUsers.filter((u) => u.id !== excludeUserId);
|
||||
if (!fetchOnly) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (operator && filteredUsers.length) {
|
||||
if (filteredUsers.length) {
|
||||
const modelPromises: Array<Promise<Model[]>> = [];
|
||||
const membership = filteredUsers.map((u) => ({
|
||||
channel_id: channelId,
|
||||
|
|
@ -108,28 +96,17 @@ export async function fetchProfilesInChannel(serverUrl: string, channelId: strin
|
|||
|
||||
return {channelId, users: filteredUsers};
|
||||
} catch (error) {
|
||||
logError('fetchProfilesInChannel', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchProfilesInChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {channelId, error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchProfilesInGroupChannels(serverUrl: string, groupChannelIds: string[], fetchOnly = false): Promise<ProfilesPerChannelRequest> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
// let's filter those channels that we already have the users
|
||||
const membersCount = await getMembersCountByChannelsId(database, groupChannelIds);
|
||||
const channelsToFetch = groupChannelIds.filter((c) => membersCount[c] <= 1);
|
||||
|
|
@ -183,16 +160,14 @@ export async function fetchProfilesInGroupChannels(serverUrl: string, groupChann
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchProfilesInGroupChannels', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchProfilesPerChannels(serverUrl: string, channelIds: string[], excludeUserId?: string, fetchOnly = false): Promise<ProfilesPerChannelRequest> {
|
||||
try {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
// Batch fetching profiles per channel by chunks of 250
|
||||
const channels = chunk(channelIds, 250);
|
||||
|
|
@ -235,39 +210,31 @@ export async function fetchProfilesPerChannels(serverUrl: string, channelIds: st
|
|||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchProfilesPerChannels', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const updateMe = async (serverUrl: string, user: Partial<UserProfile>) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const data = await client.patchMe(user);
|
||||
|
||||
if (data) {
|
||||
operator.handleUsers({prepareRecordsOnly: false, users: [data]});
|
||||
|
||||
const updatedRoles: string[] = data.roles.split(' ');
|
||||
await fetchRolesIfNeeded(serverUrl, updatedRoles);
|
||||
}
|
||||
|
||||
return {data};
|
||||
} catch (error) {
|
||||
logDebug('error on updateMe', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
let data: UserProfile;
|
||||
try {
|
||||
data = await client.patchMe(user);
|
||||
} catch (e) {
|
||||
forceLogoutIfNecessary(serverUrl, e as ClientError);
|
||||
return {error: e};
|
||||
}
|
||||
|
||||
if (data) {
|
||||
operator.handleUsers({prepareRecordsOnly: false, users: [data]});
|
||||
|
||||
const updatedRoles: string[] = data.roles.split(' ');
|
||||
await fetchRolesIfNeeded(serverUrl, updatedRoles);
|
||||
}
|
||||
|
||||
return {data};
|
||||
};
|
||||
|
||||
let ids: string[] = [];
|
||||
|
|
@ -323,79 +290,58 @@ const fetchUserOrGroupsByMentionNames = async (serverUrl: string, mentions: stri
|
|||
if (groupsToFetch.length) {
|
||||
await fetchGroupsByNames(serverUrl, groupsToFetch, false);
|
||||
}
|
||||
return {data: true};
|
||||
} catch (e) {
|
||||
return {error: e};
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchUserOrGroupsByMentionNames', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export async function fetchStatusByIds(serverUrl: string, userIds: string[], fetchOnly = false) {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
if (!userIds.length) {
|
||||
return {statuses: []};
|
||||
}
|
||||
|
||||
let database;
|
||||
let operator;
|
||||
try {
|
||||
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
database = result.database;
|
||||
operator = result.operator;
|
||||
} catch (e) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const statuses = await client.getStatusesByIds(userIds);
|
||||
|
||||
if (!fetchOnly && DatabaseManager.serverDatabases[serverUrl]) {
|
||||
if (operator) {
|
||||
const users = await queryUsersById(database, userIds).fetch();
|
||||
const userStatuses = statuses.reduce((result: Record<string, UserStatus>, s) => {
|
||||
result[s.user_id] = s;
|
||||
return result;
|
||||
}, {});
|
||||
if (!fetchOnly) {
|
||||
const users = await queryUsersById(database, userIds).fetch();
|
||||
const userStatuses = statuses.reduce((result: Record<string, UserStatus>, s) => {
|
||||
result[s.user_id] = s;
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
for (const user of users) {
|
||||
const status = userStatuses[user.id];
|
||||
user.prepareStatus(status?.status || General.OFFLINE);
|
||||
}
|
||||
|
||||
await operator.batchRecords(users, 'fetchStatusByIds');
|
||||
for (const user of users) {
|
||||
const status = userStatuses[user.id];
|
||||
user.prepareStatus(status?.status || General.OFFLINE);
|
||||
}
|
||||
|
||||
await operator.batchRecords(users, 'fetchStatusByIds');
|
||||
}
|
||||
|
||||
return {statuses};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchStatusByIds', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export const fetchUsersByIds = async (serverUrl: string, userIds: string[], fetchOnly = false) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
if (!userIds.length) {
|
||||
return {users: [], existingUsers: []};
|
||||
}
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const currentUser = await getCurrentUser(operator.database);
|
||||
const existingUsers = await queryUsersById(operator.database, userIds).fetch();
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const currentUser = await getCurrentUser(database);
|
||||
const existingUsers = await queryUsersById(database, userIds).fetch();
|
||||
if (userIds.includes(currentUser!.id)) {
|
||||
existingUsers.push(currentUser!);
|
||||
}
|
||||
|
|
@ -417,30 +363,22 @@ export const fetchUsersByIds = async (serverUrl: string, userIds: string[], fetc
|
|||
|
||||
return {users, existingUsers};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchUsersByIds', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchUsersByUsernames = async (serverUrl: string, usernames: string[], fetchOnly = false) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
if (!usernames.length) {
|
||||
return {users: []};
|
||||
}
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const currentUser = await getCurrentUser(operator.database);
|
||||
const existingUsers = await queryUsersByUsername(operator.database, usernames).fetch();
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const currentUser = await getCurrentUser(database);
|
||||
const existingUsers = await queryUsersByUsername(database, usernames).fetch();
|
||||
const exisitingUsersMap = existingUsers.reduce((result: Record<string, UserModel>, u) => {
|
||||
result[u.username] = u;
|
||||
return result;
|
||||
|
|
@ -461,29 +399,21 @@ export const fetchUsersByUsernames = async (serverUrl: string, usernames: string
|
|||
|
||||
return {users};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchUsersByUsernames', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchProfiles = async (serverUrl: string, page = 0, perPage: number = General.PROFILE_CHUNK_SIZE, options: any = {}, fetchOnly = false) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const users = await client.getProfiles(page, perPage, options);
|
||||
|
||||
if (!fetchOnly) {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const toStore = removeUserFromList(currentUserId, users);
|
||||
if (toStore.length) {
|
||||
await operator.handleUsers({
|
||||
|
|
@ -495,29 +425,21 @@ export const fetchProfiles = async (serverUrl: string, page = 0, perPage: number
|
|||
|
||||
return {users};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchProfiles', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchProfilesInTeam = async (serverUrl: string, teamId: string, page = 0, perPage: number = General.PROFILE_CHUNK_SIZE, sort = '', options: any = {}, fetchOnly = false) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const users = await client.getProfilesInTeam(teamId, page, perPage, sort, options);
|
||||
|
||||
if (!fetchOnly) {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const toStore = removeUserFromList(currentUserId, users);
|
||||
if (toStore.length) {
|
||||
await operator.handleUsers({
|
||||
|
|
@ -529,7 +451,8 @@ export const fetchProfilesInTeam = async (serverUrl: string, teamId: string, pag
|
|||
|
||||
return {users};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchProfilesInTeam', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -544,12 +467,12 @@ export const fetchProfilesNotInChannel = async (
|
|||
fetchOnly = false,
|
||||
) => {
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const users = await client.getProfilesNotInChannel(teamId, channelId, groupConstrained, page, perPage);
|
||||
|
||||
if (!fetchOnly && users.length) {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const toStore = removeUserFromList(currentUserId, users);
|
||||
await operator.handleUsers({
|
||||
users: toStore,
|
||||
|
|
@ -559,30 +482,21 @@ export const fetchProfilesNotInChannel = async (
|
|||
|
||||
return {users};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on fetchProfilesNotInChannel', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const searchProfiles = async (serverUrl: string, term: string, options: SearchUserOptions, fetchOnly = false) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const users = await client.searchUsers(term, options);
|
||||
|
||||
if (!fetchOnly) {
|
||||
const {database} = operator;
|
||||
const existing = await queryUsersById(database, users.map((u) => u.id)).fetchIds();
|
||||
const existingSet = new Set(existing);
|
||||
const usersToAdd = users.filter((u) => !existingSet.has(u.id));
|
||||
|
|
@ -597,48 +511,28 @@ export const searchProfiles = async (serverUrl: string, term: string, options: S
|
|||
|
||||
return {data: users};
|
||||
} catch (error) {
|
||||
logError('searchProfiles', error);
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on searchProfiles', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchMissingProfilesByIds = async (serverUrl: string, userIds: string[]) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {users} = await fetchUsersByIds(serverUrl, userIds);
|
||||
if (users) {
|
||||
const statusToLoad = users.map((u) => u.id);
|
||||
fetchStatusByIds(serverUrl, statusToLoad);
|
||||
}
|
||||
return {users};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
return {error};
|
||||
const {users} = await fetchUsersByIds(serverUrl, userIds);
|
||||
if (users) {
|
||||
const statusToLoad = users.map((u) => u.id);
|
||||
fetchStatusByIds(serverUrl, statusToLoad);
|
||||
}
|
||||
return {users};
|
||||
};
|
||||
|
||||
export const fetchMissingProfilesByUsernames = async (serverUrl: string, usernames: string[]) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
try {
|
||||
const {users} = await fetchUsersByUsernames(serverUrl, usernames);
|
||||
if (users) {
|
||||
const statusToLoad = users.map((u) => u.id);
|
||||
fetchStatusByIds(serverUrl, statusToLoad);
|
||||
}
|
||||
return {users};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
return {error};
|
||||
const {users} = await fetchUsersByUsernames(serverUrl, usernames);
|
||||
if (users) {
|
||||
const statusToLoad = users.map((u) => u.id);
|
||||
fetchStatusByIds(serverUrl, statusToLoad);
|
||||
}
|
||||
return {users};
|
||||
};
|
||||
|
||||
export async function updateAllUsersSince(serverUrl: string, since: number, fetchOnly = false) {
|
||||
|
|
@ -646,23 +540,13 @@ export async function updateAllUsersSince(serverUrl: string, since: number, fetc
|
|||
return {users: []};
|
||||
}
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const database = operator.database;
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const userIds = (await queryAllUsers(database).fetchIds()).filter((id) => id !== currentUserId);
|
||||
let userUpdates: UserProfile[] = [];
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
const userIds = (await queryAllUsers(database).fetchIds()).filter((id) => id !== currentUserId);
|
||||
userUpdates = await client.getProfilesByIds(userIds, {since});
|
||||
if (userUpdates.length && !fetchOnly) {
|
||||
const modelsToBatch: Model[] = [];
|
||||
|
|
@ -676,7 +560,9 @@ export async function updateAllUsersSince(serverUrl: string, since: number, fetc
|
|||
|
||||
await operator.batchRecords(modelsToBatch, 'updateAllUsersSince');
|
||||
}
|
||||
} catch {
|
||||
} catch (error) {
|
||||
logDebug('error on updateAllUsersSince', getFullErrorMessage(error));
|
||||
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
|
|
@ -684,25 +570,16 @@ export async function updateAllUsersSince(serverUrl: string, since: number, fetc
|
|||
}
|
||||
|
||||
export async function updateUsersNoLongerVisible(serverUrl: string, prepareRecordsOnly = false): Promise<{error?: unknown; models?: Model[]}> {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const serverDatabase = DatabaseManager.serverDatabases[serverUrl];
|
||||
if (!serverDatabase) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
const models: Model[] = [];
|
||||
try {
|
||||
const models: Model[] = [];
|
||||
const knownUsers = new Set(await client.getKnownUsers());
|
||||
const currentUserId = await getCurrentUserId(serverDatabase.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
knownUsers.add(currentUserId);
|
||||
|
||||
const allUsers = await queryAllUsers(serverDatabase.database).fetch();
|
||||
const allUsers = await queryAllUsers(database).fetch();
|
||||
for (const user of allUsers) {
|
||||
if (!knownUsers.has(user.id)) {
|
||||
user.prepareDestroyPermanently();
|
||||
|
|
@ -710,131 +587,85 @@ export async function updateUsersNoLongerVisible(serverUrl: string, prepareRecor
|
|||
}
|
||||
}
|
||||
if (models.length && !prepareRecordsOnly) {
|
||||
serverDatabase.operator.batchRecords(models, 'updateUsersNoLongerVisible');
|
||||
operator.batchRecords(models, 'updateUsersNoLongerVisible');
|
||||
}
|
||||
return {models};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on updateUsersNoLongerVisible', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {models};
|
||||
}
|
||||
|
||||
export const setStatus = async (serverUrl: string, status: UserStatus) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const data = await client.updateStatus(status);
|
||||
await updateLocalUser(serverUrl, {status: status.status});
|
||||
|
||||
return {
|
||||
data,
|
||||
};
|
||||
return {data};
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(serverUrl, error as ClientErrorProps);
|
||||
logDebug('error on setStatus', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const updateCustomStatus = async (serverUrl: string, customStatus: UserCustomStatus) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
try {
|
||||
if (!customStatus.duration) {
|
||||
delete customStatus.expires_at;
|
||||
}
|
||||
await client.updateCustomStatus(customStatus);
|
||||
return {data: true};
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on updateCustomStatus', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const removeRecentCustomStatus = async (serverUrl: string, customStatus: UserCustomStatus) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
updateRecentCustomStatuses(serverUrl, customStatus, false, true);
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
await client.removeRecentCustomStatus(customStatus);
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on removeRecentCustomStatus', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {data: true};
|
||||
};
|
||||
|
||||
export const unsetCustomStatus = async (serverUrl: string) => {
|
||||
let client: Client;
|
||||
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
await client.unsetCustomStatus();
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on unsetCustomStatus', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {data: true};
|
||||
};
|
||||
|
||||
export const setDefaultProfileImage = async (serverUrl: string, userId: string) => {
|
||||
let client: Client;
|
||||
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
await client.setDefaultProfileImage(userId);
|
||||
updateLocalUser(serverUrl, {last_picture_update: Date.now()});
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on setDefaultProfileImage', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {data: true};
|
||||
};
|
||||
|
||||
export const uploadUserProfileImage = async (serverUrl: string, localPath: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
try {
|
||||
const currentUser = await getCurrentUser(database);
|
||||
if (currentUser) {
|
||||
const endpoint = `${client.getUserRoute(currentUser.id)}/image`;
|
||||
|
|
@ -847,42 +678,31 @@ export const uploadUserProfileImage = async (serverUrl: string, localPath: strin
|
|||
},
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
return {error: e};
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on uploadUserProfileImage', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
return {error: undefined};
|
||||
};
|
||||
|
||||
export const searchUsers = async (serverUrl: string, term: string, teamId: string, channelId?: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const users = await client.autocompleteUsers(term, teamId, channelId);
|
||||
return {users};
|
||||
} catch (error) {
|
||||
logDebug('error on searchUsers', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const buildProfileImageUrl = (serverUrl: string, userId: string, timestamp = 0) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
return client.getProfilePictureUrl(userId, timestamp);
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return client.getProfilePictureUrl(userId, timestamp);
|
||||
};
|
||||
|
||||
export const autoUpdateTimezone = async (serverUrl: string) => {
|
||||
|
|
@ -891,14 +711,14 @@ export const autoUpdateTimezone = async (serverUrl: string) => {
|
|||
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
database = result.database;
|
||||
} catch (e) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
return;
|
||||
}
|
||||
|
||||
const config = await getConfig(database);
|
||||
const currentUser = await getCurrentUser(database);
|
||||
|
||||
if (!currentUser || !config || !isTimezoneEnabled(config)) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set timezone
|
||||
|
|
@ -911,26 +731,13 @@ export const autoUpdateTimezone = async (serverUrl: string) => {
|
|||
const timezone = {useAutomaticTimezone: 'true', automaticTimezone: deviceTimezone, manualTimezone: currentTimezone.manualTimezone};
|
||||
await updateMe(serverUrl, {timezone});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const fetchTeamAndChannelMembership = async (serverUrl: string, userId: string, teamId: string, channelId?: string) => {
|
||||
let operator;
|
||||
try {
|
||||
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
operator = result.operator;
|
||||
} catch (e) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const requests = await Promise.all([
|
||||
client.getTeamMember(teamId, userId),
|
||||
channelId ? client.getChannelMember(channelId, userId) : undefined,
|
||||
|
|
@ -951,8 +758,9 @@ export const fetchTeamAndChannelMembership = async (serverUrl: string, userId: s
|
|||
|
||||
const models = await Promise.all(modelPromises);
|
||||
await operator.batchRecords(models.flat(), 'fetchTeamAndChannelMembership');
|
||||
return {error: undefined};
|
||||
return {};
|
||||
} catch (error) {
|
||||
logDebug('error on searchUsers', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
@ -963,7 +771,7 @@ export const getAllSupportedTimezones = async (serverUrl: string) => {
|
|||
const allTzs = await client.getTimezones();
|
||||
return allTzs;
|
||||
} catch (error) {
|
||||
logError('FAILED TO GET ALL TIMEZONES', error);
|
||||
logDebug('error on getAllSupportedTimezones', getFullErrorMessage(error));
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,13 +78,7 @@ export async function handleCategoryDeletedEvent(serverUrl: string, msg: Websock
|
|||
|
||||
export async function handleCategoryOrderUpdatedEvent(serverUrl: string, msg: WebsocketCategoriesMessage) {
|
||||
try {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
// Update category order
|
||||
if (msg.data.order?.length) {
|
||||
|
|
|
|||
|
|
@ -24,18 +24,14 @@ import type {Model} from '@nozbe/watermelondb';
|
|||
|
||||
// Received when current user created a channel in a different client
|
||||
export async function handleChannelCreatedEvent(serverUrl: string, msg: any) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
const {team_id: teamId, channel_id: channelId} = msg.data;
|
||||
if (EphemeralStore.creatingChannel) {
|
||||
return; // We probably don't need to handle this WS because we provoked it
|
||||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (channel) {
|
||||
return; // We already have this channel
|
||||
|
|
@ -76,12 +72,9 @@ export async function handleChannelUnarchiveEvent(serverUrl: string, msg: any) {
|
|||
}
|
||||
|
||||
export async function handleChannelConvertedEvent(serverUrl: string, msg: any) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const channelId = msg.data.channel_id;
|
||||
if (EphemeralStore.isConvertingChannel(channelId)) {
|
||||
return;
|
||||
|
|
@ -97,12 +90,9 @@ export async function handleChannelConvertedEvent(serverUrl: string, msg: any) {
|
|||
}
|
||||
|
||||
export async function handleChannelUpdatedEvent(serverUrl: string, msg: any) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const updatedChannel = JSON.parse(msg.data.channel);
|
||||
const models: Model[] = await operator.handleChannel({channels: [updatedChannel], prepareRecordsOnly: true});
|
||||
const infoModel = await updateChannelInfoFromChannel(serverUrl, updatedChannel, true);
|
||||
|
|
@ -117,10 +107,7 @@ export async function handleChannelUpdatedEvent(serverUrl: string, msg: any) {
|
|||
|
||||
export async function handleChannelViewedEvent(serverUrl: string, msg: any) {
|
||||
try {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return;
|
||||
}
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const {channel_id: channelId} = msg.data;
|
||||
|
||||
|
|
@ -137,12 +124,9 @@ export async function handleChannelViewedEvent(serverUrl: string, msg: any) {
|
|||
|
||||
// This event is triggered by changes in the notify props or in the roles.
|
||||
export async function handleChannelMemberUpdatedEvent(serverUrl: string, msg: any) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const models: Model[] = [];
|
||||
|
||||
const updatedChannelMember: ChannelMembership = JSON.parse(msg.data.channelMember);
|
||||
|
|
@ -172,13 +156,6 @@ export async function handleChannelMemberUpdatedEvent(serverUrl: string, msg: an
|
|||
}
|
||||
|
||||
export async function handleDirectAddedEvent(serverUrl: string, msg: WebSocketMessage) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {database} = operator;
|
||||
|
||||
if (EphemeralStore.creatingDMorGMTeammates.length) {
|
||||
let userList: string[] | undefined;
|
||||
if ('teammate_ids' in msg.data) { // GM
|
||||
|
|
@ -199,6 +176,8 @@ export async function handleDirectAddedEvent(serverUrl: string, msg: WebSocketMe
|
|||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const {channel_id: channelId} = msg.broadcast;
|
||||
const channel = await getChannelById(database, channelId);
|
||||
if (channel) {
|
||||
|
|
@ -242,17 +221,13 @@ export async function handleDirectAddedEvent(serverUrl: string, msg: WebSocketMe
|
|||
}
|
||||
|
||||
export async function handleUserAddedToChannelEvent(serverUrl: string, msg: any) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
const userId = msg.data.user_id || msg.broadcast.userId;
|
||||
const channelId = msg.data.channel_id || msg.broadcast.channel_id;
|
||||
const {team_id: teamId} = msg.data;
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const currentUser = await getCurrentUser(database);
|
||||
const userId = msg.data.user_id || msg.broadcast.userId;
|
||||
const channelId = msg.data.channel_id || msg.broadcast.channel_id;
|
||||
const {team_id: teamId} = msg.data;
|
||||
const models: Model[] = [];
|
||||
|
||||
if (userId === currentUser?.id) {
|
||||
|
|
@ -363,32 +338,26 @@ export async function handleUserRemovedFromChannelEvent(serverUrl: string, msg:
|
|||
}
|
||||
|
||||
export async function handleChannelDeletedEvent(serverUrl: string, msg: WebSocketMessage) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
const {channel_id: channelId, delete_at: deleteAt} = msg.data;
|
||||
if (EphemeralStore.isLeavingChannel(channelId) || EphemeralStore.isArchivingChannel(channelId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
const {channel_id: channelId, delete_at: deleteAt} = msg.data;
|
||||
if (EphemeralStore.isLeavingChannel(channelId) || EphemeralStore.isArchivingChannel(channelId)) {
|
||||
return;
|
||||
}
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const currentChannel = await getCurrentChannel(database);
|
||||
const user = await getCurrentUser(database);
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
|
||||
const config = await getConfig(database);
|
||||
|
||||
await setChannelDeleteAt(serverUrl, channelId, deleteAt);
|
||||
|
||||
if (user.isGuest) {
|
||||
updateUsersNoLongerVisible(serverUrl);
|
||||
}
|
||||
|
||||
const currentChannel = await getCurrentChannel(database);
|
||||
const config = await getConfig(database);
|
||||
|
||||
if (config?.ExperimentalViewArchivedChannels !== 'true') {
|
||||
if (currentChannel && currentChannel.id === channelId) {
|
||||
await handleKickFromChannel(serverUrl, channelId, Events.CHANNEL_ARCHIVED);
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ export async function handlePostEdited(serverUrl: string, msg: WebSocketMessage)
|
|||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
let post: Post;
|
||||
try {
|
||||
|
|
@ -204,7 +205,6 @@ export async function handlePostEdited(serverUrl: string, msg: WebSocketMessage)
|
|||
}
|
||||
|
||||
const models: Model[] = [];
|
||||
const {database} = operator;
|
||||
|
||||
const oldPost = await getPostById(database, post.id);
|
||||
if (!oldPost) {
|
||||
|
|
@ -223,7 +223,7 @@ export async function handlePostEdited(serverUrl: string, msg: WebSocketMessage)
|
|||
}
|
||||
|
||||
let actionType: string = ActionType.POSTS.RECEIVED_NEW;
|
||||
const isCRTEnabled = await getIsCRTEnabled(operator.database);
|
||||
const isCRTEnabled = await getIsCRTEnabled(database);
|
||||
if (isCRTEnabled && post.root_id) {
|
||||
actionType = ActionType.POSTS.RECEIVED_IN_THREAD;
|
||||
}
|
||||
|
|
@ -240,12 +240,8 @@ export async function handlePostEdited(serverUrl: string, msg: WebSocketMessage)
|
|||
}
|
||||
|
||||
export async function handlePostDeleted(serverUrl: string, msg: WebSocketMessage) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const {database} = operator;
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const post: Post = JSON.parse(msg.data.post);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,9 @@ import DatabaseManager from '@database/manager';
|
|||
import {queryReaction} from '@queries/servers/reaction';
|
||||
|
||||
export async function handleAddCustomEmoji(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const emoji: CustomEmoji = JSON.parse(msg.data.emoji);
|
||||
await operator.handleCustomEmojis({
|
||||
prepareRecordsOnly: false,
|
||||
|
|
@ -22,12 +19,9 @@ export async function handleAddCustomEmoji(serverUrl: string, msg: WebSocketMess
|
|||
}
|
||||
|
||||
export async function handleReactionAddedToPostEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const reaction: Reaction = JSON.parse(msg.data.reaction);
|
||||
await operator.handleReactions({
|
||||
prepareRecordsOnly: false,
|
||||
|
|
@ -43,12 +37,9 @@ export async function handleReactionAddedToPostEvent(serverUrl: string, msg: Web
|
|||
}
|
||||
|
||||
export async function handleReactionRemovedFromPostEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const msgReaction: Reaction = JSON.parse(msg.data.reaction);
|
||||
const reaction = await queryReaction(database, msgReaction.emoji_name, msgReaction.post_id, msgReaction.user_id).fetch();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,15 +10,12 @@ import {getCurrentUser} from '@queries/servers/user';
|
|||
import type {Model} from '@nozbe/watermelondb';
|
||||
|
||||
export async function handleRoleUpdatedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only update Role records that exist in the Role Table
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
// only update Role records that exist in the Role Table
|
||||
const role: Role = JSON.parse(msg.data.role);
|
||||
const dbRole = await getRoleById(operator.database, role.id);
|
||||
const dbRole = await getRoleById(database, role.id);
|
||||
if (!dbRole) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -37,8 +34,9 @@ export async function handleUserRoleUpdatedEvent(serverUrl: string, msg: WebSock
|
|||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
if (currentUserId !== msg.data.user_id) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -58,7 +56,7 @@ export async function handleUserRoleUpdatedEvent(serverUrl: string, msg: WebSock
|
|||
}
|
||||
|
||||
// update User Table record
|
||||
const user = await getCurrentUser(operator.database);
|
||||
const user = await getCurrentUser(database);
|
||||
if (user) {
|
||||
user!.prepareUpdate((u) => {
|
||||
u.roles = msg.data.roles;
|
||||
|
|
@ -70,19 +68,16 @@ export async function handleUserRoleUpdatedEvent(serverUrl: string, msg: WebSock
|
|||
}
|
||||
|
||||
export async function handleTeamMemberRoleUpdatedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const member: TeamMembership = JSON.parse(msg.data.member);
|
||||
|
||||
if (member.delete_at > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentUserId = await getCurrentUserId(operator.database);
|
||||
const currentUserId = await getCurrentUserId(database);
|
||||
if (currentUserId !== member.user_id) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,16 +8,13 @@ import DatabaseManager from '@database/manager';
|
|||
import {getConfig, getLicense} from '@queries/servers/system';
|
||||
|
||||
export async function handleLicenseChangedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const license = msg.data.license;
|
||||
const systems: IdValue[] = [{id: SYSTEM_IDENTIFIERS.LICENSE, value: JSON.stringify(license)}];
|
||||
|
||||
const prevLicense = await getLicense(operator.database);
|
||||
const prevLicense = await getLicense(database);
|
||||
await operator.handleSystem({systems, prepareRecordsOnly: false});
|
||||
|
||||
if (license?.LockTeammateNameDisplay && (prevLicense?.LockTeammateNameDisplay !== license.LockTeammateNameDisplay)) {
|
||||
|
|
@ -29,14 +26,10 @@ export async function handleLicenseChangedEvent(serverUrl: string, msg: WebSocke
|
|||
}
|
||||
|
||||
export async function handleConfigChangedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const config = msg.data.config;
|
||||
const prevConfig = await getConfig(operator.database);
|
||||
const prevConfig = await getConfig(database);
|
||||
await storeConfig(serverUrl, config);
|
||||
if (config?.LockTeammateNameDisplay && (prevConfig?.LockTeammateNameDisplay !== config.LockTeammateNameDisplay)) {
|
||||
updateDmGmDisplayName(serverUrl);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {getCurrentTeam, prepareMyTeams, queryMyTeamsByIds} from '@queries/server
|
|||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {setTeamLoading} from '@store/team_load_store';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
|
|
@ -73,7 +74,7 @@ export async function handleTeamRestored(serverUrl: string, msg: WebSocketMessag
|
|||
if (markedAsLoading) {
|
||||
setTeamLoading(serverUrl, false);
|
||||
}
|
||||
logDebug('cannot handle restore team websocket event', error);
|
||||
logDebug('cannot handle restore team websocket event', getFullErrorMessage(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -106,14 +107,11 @@ export async function handleLeaveTeamEvent(serverUrl: string, msg: WebSocketMess
|
|||
}
|
||||
|
||||
export async function handleUpdateTeamEvent(serverUrl: string, msg: WebSocketMessage) {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl];
|
||||
if (!database) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const team: Team = JSON.parse(msg.data.team);
|
||||
database.operator.handleTeam({
|
||||
operator.handleTeam({
|
||||
teams: [team],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,10 +8,8 @@ import EphemeralStore from '@store/ephemeral_store';
|
|||
|
||||
export async function handleThreadUpdatedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
|
||||
try {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return;
|
||||
}
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const thread: Thread = JSON.parse(msg.data.thread);
|
||||
let teamId = msg.broadcast.team_id;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,23 +2,18 @@
|
|||
// See LICENSE.txt for license information.
|
||||
import {MEMBERS_PER_PAGE} from '@constants/graphql';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import QueryNames from './constants';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
|
||||
const doGQLQuery = async (serverUrl: string, query: string, variables: {[name: string]: any}, operationName: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const response = await client.doFetch('/api/v5/graphql', {method: 'post', body: {query, variables, operationName}}) as GQLResponse;
|
||||
return response;
|
||||
} catch (error) {
|
||||
logDebug('error on doGQLQuery', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ export default class ClientBase {
|
|||
defaultMessage: 'Received invalid response from the server.',
|
||||
},
|
||||
url,
|
||||
details: error,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -312,8 +313,8 @@ export default class ClientBase {
|
|||
}
|
||||
|
||||
throw new ClientError(this.apiClient.baseUrl, {
|
||||
message: response.data?.message || '',
|
||||
server_error_id: response.data?.id,
|
||||
message: response.data?.message as string || `Response with status code ${response.code}`,
|
||||
server_error_id: response.data?.id as string,
|
||||
status_code: response.code,
|
||||
url,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import {cleanUrlForLogging} from '@utils/url';
|
|||
|
||||
export default class ClientError extends Error {
|
||||
url: string;
|
||||
intl: { defaultMessage: string; id: string; values?: any };
|
||||
server_error_id: any;
|
||||
status_code: any;
|
||||
details: Error;
|
||||
constructor(baseUrl: string, data: any) {
|
||||
intl?: ClientErrorIntl;
|
||||
server_error_id?: string;
|
||||
status_code?: number;
|
||||
details?: unknown;
|
||||
constructor(baseUrl: string, data: ClientErrorProps) {
|
||||
super(data.message + ': ' + cleanUrlForLogging(baseUrl, data.url));
|
||||
|
||||
this.message = data.message;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ const SlashSuggestion = ({
|
|||
if (!mounted.current) {
|
||||
return;
|
||||
}
|
||||
if (res.error) {
|
||||
if ('error' in res) {
|
||||
updateSuggestions(emptySuggestionList);
|
||||
} else if (res.suggestions.length === 0) {
|
||||
updateSuggestions(emptySuggestionList);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ const ManageMembersLabel = ({canRemoveUser, channelId, manageOption, testID, use
|
|||
|
||||
const updateChannelMemberSchemeRole = useCallback(async (schemeAdmin: boolean) => {
|
||||
const result = await updateChannelMemberSchemeRoles(serverUrl, channelId, userId, true, schemeAdmin);
|
||||
if (result.error) {
|
||||
if ('error' in result) {
|
||||
alertErrorWithFallback(intl, result.error, messages.role_change_error);
|
||||
}
|
||||
await dismissBottomSheet();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {render} from '@testing-library/react-native';
|
||||
import React from 'react';
|
||||
|
||||
import {Preferences} from '@constants';
|
||||
import {renderWithIntl} from '@test/intl-test-helper';
|
||||
|
||||
import ErrorTextComponent from './index';
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ describe('ErrorText', () => {
|
|||
};
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = render(
|
||||
const wrapper = renderWithIntl(
|
||||
<ErrorTextComponent {...baseProps}/>,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {type StyleProp, Text, type TextStyle, type ViewStyle} from 'react-native';
|
||||
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {getErrorMessage} from '@utils/errors';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
type ErrorProps = {
|
||||
error: ErrorText;
|
||||
error: unknown;
|
||||
testID?: string;
|
||||
textStyle?: StyleProp<ViewStyle> | StyleProp<TextStyle>;
|
||||
}
|
||||
|
|
@ -17,20 +18,8 @@ type ErrorProps = {
|
|||
const ErrorTextComponent = ({error, testID, textStyle}: ErrorProps) => {
|
||||
const theme = useTheme();
|
||||
const style = getStyleSheet(theme);
|
||||
const message = typeof (error) === 'string' ? error : error.message;
|
||||
|
||||
if (typeof (error) !== 'string' && error.intl) {
|
||||
const {intl} = error;
|
||||
return (
|
||||
<FormattedText
|
||||
testID={testID}
|
||||
id={intl.id}
|
||||
defaultMessage={intl.defaultMessage}
|
||||
values={intl.values}
|
||||
style={[style.errorLabel, textStyle]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const intl = useIntl();
|
||||
const message = getErrorMessage(error, intl);
|
||||
|
||||
return (
|
||||
<Text
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ import {useServerUrl} from '@context/server';
|
|||
import {useTheme} from '@context/theme';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {alertDownloadDocumentDisabled, alertDownloadFailed, alertFailedToOpenDocument} from '@utils/document';
|
||||
import {getFullErrorMessage, isErrorWithMessage} from '@utils/errors';
|
||||
import {fileExists, getLocalFilePathFromFile} from '@utils/file';
|
||||
import {emptyFunction} from '@utils/general';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import FileIcon from './file_icon';
|
||||
|
||||
|
|
@ -90,7 +92,8 @@ const DocumentFile = forwardRef<DocumentFileRef, DocumentFileProps>(({background
|
|||
setDownloading(false);
|
||||
setProgress(0);
|
||||
|
||||
if ((error as Error).message !== 'cancelled') {
|
||||
if (!isErrorWithMessage(error) || error.message !== 'cancelled') {
|
||||
logDebug('error on downloadAndPreviewFile', getFullErrorMessage(error));
|
||||
alertDownloadFailed(intl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {useServerUrl} from '@context/server';
|
|||
import DraftUploadManager from '@managers/draft_upload_manager';
|
||||
import * as DraftUtils from '@utils/draft';
|
||||
import {isReactionMatch} from '@utils/emoji/helpers';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {preventDoubleTap} from '@utils/tap';
|
||||
import {confirmOutOfOfficeDisabled} from '@utils/user';
|
||||
|
||||
|
|
@ -197,7 +198,7 @@ export default function SendHandler({
|
|||
setSendingMessage(false);
|
||||
|
||||
if (error) {
|
||||
const errorMessage = typeof (error) === 'string' ? error : error.message;
|
||||
const errorMessage = getFullErrorMessage(error);
|
||||
DraftUtils.alertSlashCommandFailed(intl, errorMessage);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import DatabaseManager from '@database/manager';
|
|||
import {getChannelById} from '@queries/servers/channel';
|
||||
import {getConfig, getCurrentChannelId, getCurrentTeamId, getCurrentUserId, observeConfigBooleanValue} from '@queries/servers/system';
|
||||
import {validateBindings} from '@utils/apps';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import NetworkManager from './network_manager';
|
||||
|
|
@ -129,7 +130,7 @@ class AppsManager {
|
|||
this.commandForms[serverUrl] = {};
|
||||
}
|
||||
} catch (error) {
|
||||
logDebug('Error fetching apps', error);
|
||||
logDebug('error on fetchBindings', getFullErrorMessage(error));
|
||||
this.handleError(serverUrl);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {AppState, type AppStateStatus} from 'react-native';
|
|||
import {updateDraftFile} from '@actions/local/draft';
|
||||
import {uploadFile} from '@actions/remote/file';
|
||||
import {PROGRESS_TIME_TO_STORE} from '@constants/files';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
|
||||
import type {ClientResponse, ClientResponseError} from '@mattermost/react-native-network-client';
|
||||
|
||||
|
|
@ -63,7 +64,7 @@ class DraftUploadManager {
|
|||
|
||||
const {error, cancel} = uploadFile(serverUrl, file, channelId, onProgress, onComplete, onError, skipBytes);
|
||||
if (error) {
|
||||
this.handleError(error.message, file.clientId!);
|
||||
this.handleError(getFullErrorMessage(error), file.clientId!);
|
||||
return;
|
||||
}
|
||||
this.handlers[file.clientId!].cancel = cancel;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ import {setScreensOrientation} from '@screens/navigation';
|
|||
import {handleDeepLink} from '@utils/deep_link';
|
||||
import {logError} from '@utils/log';
|
||||
|
||||
import type {jsAndNativeErrorHandler} from '@typings/global/error_handling';
|
||||
|
||||
type LinkingCallbackArg = {url: string};
|
||||
|
||||
const {SplitView} = NativeModules;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class ServerIntegrationsManager {
|
|||
|
||||
try {
|
||||
const res = await fetchCommands(this.serverUrl, teamId);
|
||||
if (res.error) {
|
||||
if ('error' in res) {
|
||||
return [];
|
||||
}
|
||||
this.commands[teamId] = res.commands;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ class NetworkManager {
|
|||
defaultMessage: 'Can’t find this server. Check spelling and URL format.',
|
||||
},
|
||||
url: serverUrl,
|
||||
details: error,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,21 +36,19 @@ import {getThreadById} from '@queries/servers/thread';
|
|||
import {getCurrentUser, getUserById} from '@queries/servers/user';
|
||||
import {dismissAllModalsAndPopToScreen} from '@screens/navigation';
|
||||
import NavigationStore from '@store/navigation_store';
|
||||
import {logWarning} from '@utils/log';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {displayUsername, getUserIdFromChannelName, isSystemAdmin} from '@utils/user';
|
||||
|
||||
import {newConnection} from '../connection/connection';
|
||||
|
||||
import type {
|
||||
ApiResp,
|
||||
AudioDevice,
|
||||
Call,
|
||||
CallParticipant,
|
||||
CallsConnection,
|
||||
} from '@calls/types/calls';
|
||||
import type {Client} from '@client/rest';
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {CallChannelState, CallRecordingState, CallState, EmojiData} from '@mattermost/calls/lib/types';
|
||||
import type {CallChannelState, CallState, EmojiData} from '@mattermost/calls/lib/types';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
let connection: CallsConnection | null = null;
|
||||
|
|
@ -67,38 +65,27 @@ export const loadConfig = async (serverUrl: string, force = false) => {
|
|||
}
|
||||
}
|
||||
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const data = await client.getCallsConfig();
|
||||
const nextConfig = {...data, last_retrieved_at: now};
|
||||
setConfig(serverUrl, nextConfig);
|
||||
return {data: nextConfig};
|
||||
} catch (error) {
|
||||
logDebug('error on loadConfig', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = await client.getCallsConfig();
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
return {error};
|
||||
}
|
||||
|
||||
const nextConfig = {...data, last_retrieved_at: now};
|
||||
setConfig(serverUrl, nextConfig);
|
||||
return {data: nextConfig};
|
||||
};
|
||||
|
||||
export const loadCalls = async (serverUrl: string, userId: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
let resp: CallChannelState[] = [];
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
resp = await client.getCalls() || [];
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on loadCalls', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
|
|
@ -127,18 +114,13 @@ export const loadCalls = async (serverUrl: string, userId: string) => {
|
|||
};
|
||||
|
||||
export const loadCallForChannel = async (serverUrl: string, channelId: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
let resp: CallChannelState;
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
resp = await client.getCallForChannel(channelId);
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on loadCallForChannel', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
|
|
@ -189,18 +171,13 @@ export const loadConfigAndCalls = async (serverUrl: string, userId: string) => {
|
|||
};
|
||||
|
||||
export const checkIsCallsPluginEnabled = async (serverUrl: string) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
let data: ClientPluginManifest[] = [];
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
data = await client.getPluginsManifests();
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on checkIsCallsPluginEnabled', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
|
|
@ -214,24 +191,18 @@ export const checkIsCallsPluginEnabled = async (serverUrl: string) => {
|
|||
};
|
||||
|
||||
export const enableChannelCalls = async (serverUrl: string, channelId: string, enable: boolean) => {
|
||||
let client: Client;
|
||||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const res = await client.enableChannelCalls(channelId, enable);
|
||||
if (res.enabled === enable) {
|
||||
setChannelEnabled(serverUrl, channelId, enable);
|
||||
}
|
||||
return {};
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on enableChannelCalls', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
export const joinCall = async (
|
||||
|
|
@ -240,7 +211,7 @@ export const joinCall = async (
|
|||
userId: string,
|
||||
hasMicPermission: boolean,
|
||||
title?: string,
|
||||
): Promise<{ error?: string | Error; data?: string }> => {
|
||||
): Promise<{ error?: unknown; data?: string }> => {
|
||||
// Edge case: calls was disabled when app loaded, and then enabled, but app hasn't
|
||||
// reconnected its websocket since then (i.e., hasn't called batchLoadCalls yet)
|
||||
const {data: enabled} = await checkIsCallsPluginEnabled(serverUrl);
|
||||
|
|
@ -259,9 +230,9 @@ export const joinCall = async (
|
|||
connection = await newConnection(serverUrl, channelId, () => {
|
||||
myselfLeftCall();
|
||||
}, setScreenShareURL, hasMicPermission, title);
|
||||
} catch (error: unknown) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
return {error: error as Error};
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return {error};
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -419,52 +390,43 @@ export const getEndCallMessage = async (serverUrl: string, channelId: string, cu
|
|||
};
|
||||
|
||||
export const endCall = async (serverUrl: string, channelId: string) => {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
let data: ApiResp;
|
||||
try {
|
||||
data = await client.endCall(channelId);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const data = await client.endCall(channelId);
|
||||
return data;
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logDebug('error on endCall', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const startCallRecording = async (serverUrl: string, callId: string) => {
|
||||
needsRecordingErrorAlert();
|
||||
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
let data: ApiResp | CallRecordingState;
|
||||
try {
|
||||
data = await client.startCallRecording(callId);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const data = await client.startCallRecording(callId);
|
||||
return data;
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logWarning('start call recording returned:', error);
|
||||
logDebug('error on startCallRecording', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const stopCallRecording = async (serverUrl: string, callId: string) => {
|
||||
needsRecordingWillBePostedAlert();
|
||||
needsRecordingErrorAlert();
|
||||
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
|
||||
let data: ApiResp | CallRecordingState;
|
||||
try {
|
||||
data = await client.stopCallRecording(callId);
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const data = await client.stopCallRecording(callId);
|
||||
return data;
|
||||
} catch (error) {
|
||||
await forceLogoutIfNecessary(serverUrl, error as ClientError);
|
||||
logWarning('stop call recording returned:', error);
|
||||
logDebug('error on stopCallRecording', getFullErrorMessage(error));
|
||||
await forceLogoutIfNecessary(serverUrl, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
// handleCallsSlashCommand will return true if the slash command was handled
|
||||
|
|
@ -610,7 +572,7 @@ const handleEndCall = async (serverUrl: string, channelId: string, currentUserId
|
|||
try {
|
||||
await endCall(serverUrl, channelId);
|
||||
} catch (e) {
|
||||
const err = (e as ClientError).message || 'unable to complete command, see server logs';
|
||||
const err = getFullErrorMessage(e);
|
||||
Alert.alert('Error', `Error: ${err}`);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {getICEServersConfigs} from '@calls/utils';
|
|||
import {WebsocketEvents} from '@constants';
|
||||
import {getServerCredentials} from '@init/credentials';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug, logError, logInfo, logWarning} from '@utils/log';
|
||||
|
||||
import {WebSocketClient, wsReconnectionTimeoutErr} from './websocket_client';
|
||||
|
|
@ -186,7 +187,7 @@ export async function newConnection(
|
|||
try {
|
||||
config = await client.getCallsConfig();
|
||||
} catch (err) {
|
||||
logError('FETCHING CALLS CONFIG:', err);
|
||||
logError('FETCHING CALLS CONFIG:', getFullErrorMessage(err));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +196,7 @@ export async function newConnection(
|
|||
try {
|
||||
iceConfigs.push(...await client.genTURNCredentials());
|
||||
} catch (err) {
|
||||
logWarning('failed to fetch TURN credentials:', err);
|
||||
logWarning('failed to fetch TURN credentials:', getFullErrorMessage(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ import {errorAlert} from '@calls/utils';
|
|||
import {useServerUrl} from '@context/server';
|
||||
import {useAppState} from '@hooks/device';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
|
||||
import type {Client} from '@client/rest';
|
||||
import type ClientError from '@client/rest/error';
|
||||
|
||||
export const useTryCallsFunction = (fn: () => void) => {
|
||||
const intl = useIntl();
|
||||
|
|
@ -29,11 +29,19 @@ export const useTryCallsFunction = (fn: () => void) => {
|
|||
try {
|
||||
client = NetworkManager.getClient(serverUrl);
|
||||
} catch (error) {
|
||||
setClientError((error as ClientError).message);
|
||||
setClientError(getFullErrorMessage(error));
|
||||
}
|
||||
}
|
||||
const tryFn = useCallback(async () => {
|
||||
if (client && await client.getEnabled()) {
|
||||
let enabled;
|
||||
try {
|
||||
enabled = await client?.getEnabled();
|
||||
} catch (error) {
|
||||
errorAlert(getFullErrorMessage(error), intl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
setMsgPostfix('');
|
||||
fn();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export const queryCategoriesByTeamIds = (database: Database, teamIds: string[])
|
|||
|
||||
export async function prepareCategoriesAndCategoriesChannels(operator: ServerDataOperator, categories: CategoryWithChannels[], prune = false) {
|
||||
try {
|
||||
const {database} = operator;
|
||||
const modelPromises: Array<Promise<Model[]>> = [
|
||||
prepareCategories(operator, categories),
|
||||
prepareCategoryChannels(operator, categories),
|
||||
|
|
@ -49,7 +50,7 @@ export async function prepareCategoriesAndCategoriesChannels(operator: ServerDat
|
|||
|
||||
// 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(operator.database, teamIds).fetch();
|
||||
const localCategories = await queryCategoriesByTeamIds(database, teamIds).fetch();
|
||||
const customCategories = localCategories.filter((c) => c.type === 'custom');
|
||||
for await (const custom of customCategories) {
|
||||
if (!remoteCategoryIds.has(custom.id)) {
|
||||
|
|
|
|||
|
|
@ -332,7 +332,8 @@ export const observeCurrentChannel = (database: Database) => {
|
|||
|
||||
export async function deleteChannelMembership(operator: ServerDataOperator, userId: string, channelId: string, prepareRecordsOnly = false) {
|
||||
try {
|
||||
const channelMembership = await operator.database.get<ChannelMembershipModel>(CHANNEL_MEMBERSHIP).query(Q.where('user_id', Q.eq(userId)), Q.where('channel_id', Q.eq(channelId))).fetch();
|
||||
const {database} = operator;
|
||||
const channelMembership = await database.get<ChannelMembershipModel>(CHANNEL_MEMBERSHIP).query(Q.where('user_id', Q.eq(userId)), Q.where('channel_id', Q.eq(channelId))).fetch();
|
||||
const models: Model[] = [];
|
||||
for (const membership of channelMembership) {
|
||||
models.push(membership.prepareDestroyPermanently());
|
||||
|
|
|
|||
|
|
@ -327,7 +327,8 @@ export const observeWebsocketLastDisconnected = (database: Database) => {
|
|||
};
|
||||
|
||||
export const resetWebSocketLastDisconnected = async (operator: ServerDataOperator, prepareRecordsOnly = false) => {
|
||||
const lastDisconnectedAt = await getWebSocketLastDisconnected(operator.database);
|
||||
const {database} = operator;
|
||||
const lastDisconnectedAt = await getWebSocketLastDisconnected(database);
|
||||
|
||||
if (lastDisconnectedAt) {
|
||||
return operator.handleSystem({systems: [{
|
||||
|
|
|
|||
|
|
@ -46,14 +46,16 @@ export const addChannelToTeamHistory = async (operator: ServerDataOperator, team
|
|||
let tch: TeamChannelHistory|undefined;
|
||||
|
||||
try {
|
||||
const {database} = operator;
|
||||
|
||||
// Exlude GLOBAL_THREADS from channel check
|
||||
if (channelId !== Screens.GLOBAL_THREADS) {
|
||||
const myChannel = (await operator.database.get<MyChannelModel>(MY_CHANNEL).find(channelId));
|
||||
const myChannel = (await database.get<MyChannelModel>(MY_CHANNEL).find(channelId));
|
||||
if (!myChannel) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
const teamChannelHistory = await getTeamChannelHistory(operator.database, teamId);
|
||||
const teamChannelHistory = await getTeamChannelHistory(database, teamId);
|
||||
const channelIdSet = new Set(teamChannelHistory);
|
||||
if (channelIdSet.has(channelId)) {
|
||||
channelIdSet.delete(channelId);
|
||||
|
|
@ -111,7 +113,8 @@ export const removeChannelFromTeamHistory = async (operator: ServerDataOperator,
|
|||
let tch: TeamChannelHistory;
|
||||
|
||||
try {
|
||||
const teamChannelHistory = await getTeamChannelHistory(operator.database, teamId);
|
||||
const {database} = operator;
|
||||
const teamChannelHistory = await getTeamChannelHistory(database, teamId);
|
||||
const channelIdSet = new Set(teamChannelHistory);
|
||||
if (channelIdSet.has(channelId)) {
|
||||
channelIdSet.delete(channelId);
|
||||
|
|
@ -132,7 +135,8 @@ export const removeChannelFromTeamHistory = async (operator: ServerDataOperator,
|
|||
};
|
||||
|
||||
export const addTeamToTeamHistory = async (operator: ServerDataOperator, teamId: string, prepareRecordsOnly = false) => {
|
||||
const teamHistory = (await getTeamHistory(operator.database));
|
||||
const {database} = operator;
|
||||
const teamHistory = (await getTeamHistory(database));
|
||||
const teamHistorySet = new Set(teamHistory);
|
||||
if (teamHistorySet.has(teamId)) {
|
||||
teamHistorySet.delete(teamId);
|
||||
|
|
@ -144,7 +148,8 @@ export const addTeamToTeamHistory = async (operator: ServerDataOperator, teamId:
|
|||
};
|
||||
|
||||
export const removeTeamFromTeamHistory = async (operator: ServerDataOperator, teamId: string, prepareRecordsOnly = false) => {
|
||||
const teamHistory = (await getTeamHistory(operator.database));
|
||||
const {database} = operator;
|
||||
const teamHistory = (await getTeamHistory(database));
|
||||
const teamHistorySet = new Set(teamHistory);
|
||||
if (!teamHistorySet.has(teamId)) {
|
||||
return undefined;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ export const prepareThreadsFromReceivedPosts = async (operator: ServerDataOperat
|
|||
const models: Model[] = [];
|
||||
const threads: ThreadWithLastFetchedAt[] = [];
|
||||
const toUpdate: {[rootId: string]: number | undefined} = {};
|
||||
const {database} = operator;
|
||||
let processedThreads: Set<string> | undefined;
|
||||
|
||||
posts.forEach((post: Post) => {
|
||||
|
|
@ -139,7 +140,7 @@ export const prepareThreadsFromReceivedPosts = async (operator: ServerDataOperat
|
|||
|
||||
const toUpdateKeys = Object.keys(toUpdate);
|
||||
if (toUpdateKeys.length) {
|
||||
const toUpdateThreads = await Promise.all(toUpdateKeys.map((key) => getThreadById(operator.database, key)));
|
||||
const toUpdateThreads = await Promise.all(toUpdateKeys.map((key) => getThreadById(database, key)));
|
||||
for (const thread of toUpdateThreads) {
|
||||
if (thread && !processedThreads?.has(thread.id)) {
|
||||
const model = thread.prepareUpdate((record) => {
|
||||
|
|
|
|||
|
|
@ -68,11 +68,11 @@ function AppsFormContainer({
|
|||
const creq = createCallRequest(currentForm.submit, context, {}, submission);
|
||||
const res = await doAppSubmit<FormResponseData>(serverUrl, creq, intl);
|
||||
|
||||
if (res.error) {
|
||||
if ('error' in res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
const callResp = res.data!;
|
||||
const callResp = res.data;
|
||||
switch (callResp.type) {
|
||||
case AppCallResponseTypes.OK:
|
||||
if (callResp.text) {
|
||||
|
|
|
|||
|
|
@ -270,9 +270,9 @@ const CustomStatus = ({
|
|||
dispatchStatus({type: 'fromUserCustomStatus', status});
|
||||
}
|
||||
} else if (storedStatus?.emoji) {
|
||||
const unsetResponse = await unsetCustomStatus(serverUrl);
|
||||
const {error} = await unsetCustomStatus(serverUrl);
|
||||
|
||||
if (unsetResponse?.data) {
|
||||
if (!error) {
|
||||
updateLocalCustomStatus(serverUrl, currentUser, undefined);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
|||
import {typography} from '@utils/typography';
|
||||
|
||||
type DisplayErrorProps = {
|
||||
error: Partial<ClientErrorProps> | string;
|
||||
error: unknown;
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ const EditProfile = ({
|
|||
username: currentUser.username,
|
||||
});
|
||||
const [canSave, setCanSave] = useState(false);
|
||||
const [error, setError] = useState<ErrorText | undefined>();
|
||||
const [error, setError] = useState<unknown>();
|
||||
const [updating, setUpdating] = useState(false);
|
||||
|
||||
const buttonText = intl.formatMessage({id: 'mobile.account.settings.save', defaultMessage: 'Save'});
|
||||
|
|
@ -135,7 +135,7 @@ const EditProfile = ({
|
|||
const now = Date.now();
|
||||
const {error: uploadError} = await uploadUserProfileImage(serverUrl, localPath);
|
||||
if (uploadError) {
|
||||
resetScreen(uploadError as Error);
|
||||
resetScreen(uploadError);
|
||||
return;
|
||||
}
|
||||
updateLocalUser(serverUrl, {last_picture_update: now});
|
||||
|
|
@ -146,7 +146,7 @@ const EditProfile = ({
|
|||
if (hasUpdateUserInfo.current) {
|
||||
const {error: reqError} = await updateMe(serverUrl, newUserInfo);
|
||||
if (reqError) {
|
||||
resetScreen(reqError as Error);
|
||||
resetScreen(reqError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -154,7 +154,7 @@ const EditProfile = ({
|
|||
close();
|
||||
return;
|
||||
} catch (e) {
|
||||
resetScreen(e as Error);
|
||||
resetScreen(e);
|
||||
}
|
||||
}), [userInfo, enableSaveButton]);
|
||||
|
||||
|
|
@ -179,8 +179,8 @@ const EditProfile = ({
|
|||
enableSaveButton(didChange);
|
||||
}, [userInfo, currentUser, enableSaveButton]);
|
||||
|
||||
const resetScreen = useCallback((resetError: Error) => {
|
||||
setError(resetError?.message);
|
||||
const resetScreen = useCallback((resetError: unknown) => {
|
||||
setError(resetError);
|
||||
Keyboard.dismiss();
|
||||
setUpdating(false);
|
||||
enableSaveButton(true);
|
||||
|
|
@ -217,7 +217,7 @@ const EditProfile = ({
|
|||
style={styles.flex}
|
||||
>
|
||||
{updating && <Updating/>}
|
||||
{Boolean(error) && <ProfileError error={error!}/>}
|
||||
{Boolean(error) && <ProfileError error={error}/>}
|
||||
<View style={styles.top}>
|
||||
<UserProfilePicture
|
||||
currentUser={currentUser}
|
||||
|
|
|
|||
|
|
@ -143,9 +143,9 @@ const FilteredList = ({
|
|||
};
|
||||
|
||||
const onJoinChannel = useCallback(async (c: Channel | ChannelModel) => {
|
||||
const {error} = await joinChannelIfNeeded(serverUrl, c.id);
|
||||
const res = await joinChannelIfNeeded(serverUrl, c.id);
|
||||
const displayName = 'display_name' in c ? c.display_name : c.displayName;
|
||||
if (error) {
|
||||
if ('error' in res) {
|
||||
Alert.alert(
|
||||
'',
|
||||
formatMessage({
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@ import Toast from '@components/toast';
|
|||
import {GALLERY_FOOTER_HEIGHT} from '@constants/gallery';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {alertFailedToOpenDocument} from '@utils/document';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {fileExists, getLocalFilePathFromFile, hasWriteStoragePermission} from '@utils/file';
|
||||
import {pathWithPrefix} from '@utils/files';
|
||||
import {galleryItemToFileInfo} from '@utils/gallery';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
import type {ClientResponse, ProgressPromise} from '@mattermost/react-native-network-client';
|
||||
|
|
@ -286,6 +288,7 @@ const DownloadWithAction = ({action, item, onDownloadSuccess, setAction, gallery
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
logDebug('error on startDownload', getFullErrorMessage(e));
|
||||
setShowToast(false);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -240,14 +240,14 @@ const ServerItem = ({
|
|||
setSwitching(true);
|
||||
const result = await doPing(server.url, true);
|
||||
if (result.error) {
|
||||
alertServerError(intl, result.error as ClientErrorProps);
|
||||
alertServerError(intl, result.error);
|
||||
setSwitching(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await fetchConfigAndLicense(server.url, true);
|
||||
if (data.error) {
|
||||
alertServerError(intl, data.error as ClientErrorProps);
|
||||
alertServerError(intl, data.error);
|
||||
setSwitching(false);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import {Keyboard, TextInput, TouchableOpacity, View} from 'react-native';
|
|||
import Button from 'react-native-button';
|
||||
|
||||
import {login} from '@actions/remote/session';
|
||||
import ClientError from '@client/rest/error';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import FloatingTextInput from '@components/floating_text_input_label';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
|
|
@ -17,7 +16,7 @@ import {FORGOT_PASSWORD, MFA} from '@constants/screens';
|
|||
import {t} from '@i18n';
|
||||
import {goToScreen, loginAnimationOptions, resetToHome} from '@screens/navigation';
|
||||
import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles';
|
||||
import {isServerError} from '@utils/errors';
|
||||
import {getFullErrorMessage, isErrorWithMessage, isServerError} from '@utils/errors';
|
||||
import {preventDoubleTap} from '@utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
|
|
@ -99,11 +98,11 @@ const LoginForm = ({config, extra, serverDisplayName, launchError, launchType, l
|
|||
const signIn = async () => {
|
||||
const result: LoginActionResponse = await login(serverUrl!, {serverDisplayName, loginId: loginId.toLowerCase(), password, config, license});
|
||||
if (checkLoginResponse(result)) {
|
||||
goToHome(result.error as never);
|
||||
goToHome(result.error);
|
||||
}
|
||||
};
|
||||
|
||||
const goToHome = (loginError?: never) => {
|
||||
const goToHome = (loginError?: unknown) => {
|
||||
const hasError = launchError || Boolean(loginError);
|
||||
resetToHome({extra, launchError: hasError, launchType, serverUrl});
|
||||
};
|
||||
|
|
@ -136,18 +135,10 @@ const LoginForm = ({config, extra, serverDisplayName, launchError, launchType, l
|
|||
goToScreen(MFA, '', {goToHome, loginId, password, config, serverDisplayName, license, serverUrl, theme}, loginAnimationOptions());
|
||||
};
|
||||
|
||||
const getLoginErrorMessage = (loginError: string | ClientErrorProps | Error) => {
|
||||
if (typeof loginError === 'string') {
|
||||
return loginError;
|
||||
}
|
||||
|
||||
if (loginError instanceof ClientError) {
|
||||
const getLoginErrorMessage = (loginError: unknown) => {
|
||||
if (isServerError(loginError)) {
|
||||
const errorId = loginError.server_error_id;
|
||||
if (!errorId && loginError.message) {
|
||||
return loginError.message;
|
||||
}
|
||||
|
||||
if (errorId === 'api.user.login.invalid_credentials_email_username' || !errorId) {
|
||||
if (errorId === 'api.user.login.invalid_credentials_email_username' || (!isErrorWithMessage(loginError) && typeof loginError !== 'string')) {
|
||||
return intl.formatMessage({
|
||||
id: 'login.invalid_credentials',
|
||||
defaultMessage: 'The email and password combination is incorrect',
|
||||
|
|
@ -155,7 +146,7 @@ const LoginForm = ({config, extra, serverDisplayName, launchError, launchType, l
|
|||
}
|
||||
}
|
||||
|
||||
return loginError.message;
|
||||
return getFullErrorMessage(loginError);
|
||||
};
|
||||
|
||||
const createLoginPlaceholder = () => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-nati
|
|||
import {SafeAreaView} from 'react-native-safe-area-context';
|
||||
|
||||
import {login} from '@actions/remote/session';
|
||||
import ClientError from '@client/rest/error';
|
||||
import FloatingTextInput from '@components/floating_text_input_label';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import Loading from '@components/loading';
|
||||
|
|
@ -21,6 +20,7 @@ import {t} from '@i18n';
|
|||
import Background from '@screens/background';
|
||||
import {popTopScreen} from '@screens/navigation';
|
||||
import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles';
|
||||
import {getErrorMessage} from '@utils/errors';
|
||||
import {preventDoubleTap} from '@utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
|
@ -32,7 +32,7 @@ import type {AvailableScreens} from '@typings/screens/navigation';
|
|||
type MFAProps = {
|
||||
componentId: AvailableScreens;
|
||||
config: Partial<ClientConfig>;
|
||||
goToHome: (error?: never) => void;
|
||||
goToHome: (error?: unknown) => void;
|
||||
license: Partial<ClientLicense>;
|
||||
loginId: string;
|
||||
password: string;
|
||||
|
|
@ -143,20 +143,10 @@ const MFA = ({componentId, config, goToHome, license, loginId, password, serverD
|
|||
const result: LoginActionResponse = await login(serverUrl, {loginId, password, mfaToken: token, config, license, serverDisplayName});
|
||||
setIsLoading(false);
|
||||
if (result?.error && result.failed) {
|
||||
if (typeof result.error == 'string') {
|
||||
setError(result?.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.error instanceof ClientError && result.error.intl) {
|
||||
setError(intl.formatMessage({id: result.error.intl.id, defaultMessage: result.error.intl.defaultMessage}, result.error.intl.values));
|
||||
return;
|
||||
}
|
||||
|
||||
setError(result.error.message);
|
||||
setError(getErrorMessage(error, intl));
|
||||
return;
|
||||
}
|
||||
goToHome(result.error as never);
|
||||
goToHome(result.error);
|
||||
}), [token]);
|
||||
|
||||
const transform = useAnimatedStyle(() => {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import NetworkManager from '@managers/network_manager';
|
|||
import {getServerByDisplayName, getServerByIdentifier} from '@queries/app/servers';
|
||||
import Background from '@screens/background';
|
||||
import {dismissModal, goToScreen, loginAnimationOptions, popTopScreen} from '@screens/navigation';
|
||||
import {getErrorMessage} from '@utils/client_error';
|
||||
import {getErrorMessage} from '@utils/errors';
|
||||
import {canReceiveNotifications} from '@utils/push_proxy';
|
||||
import {loginOptions} from '@utils/server';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
|
@ -31,7 +31,6 @@ import {getServerUrlAfterRedirect, isValidUrl, sanitizeUrl} from '@utils/url';
|
|||
import ServerForm from './form';
|
||||
import ServerHeader from './header';
|
||||
|
||||
import type ClientError from '@client/rest/error';
|
||||
import type {DeepLinkWithData, LaunchProps} from '@typings/launch';
|
||||
import type {AvailableScreens} from '@typings/screens/navigation';
|
||||
|
||||
|
|
@ -301,7 +300,7 @@ const Server = ({
|
|||
const nurl = serverUrl.replace('https:', 'http:');
|
||||
pingServer(nurl, false);
|
||||
} else {
|
||||
setUrlError(getErrorMessage(result.error as ClientError, intl));
|
||||
setUrlError(getErrorMessage(result.error, intl));
|
||||
setButtonDisabled(true);
|
||||
setConnecting(false);
|
||||
}
|
||||
|
|
@ -312,7 +311,7 @@ const Server = ({
|
|||
const data = await fetchConfigAndLicense(serverUrl, true);
|
||||
if (data.error) {
|
||||
setButtonDisabled(true);
|
||||
setUrlError(getErrorMessage(data.error as ClientError, intl));
|
||||
setUrlError(getErrorMessage(data.error, intl));
|
||||
setConnecting(false);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-nati
|
|||
import {SafeAreaView} from 'react-native-safe-area-context';
|
||||
|
||||
import {ssoLogin} from '@actions/remote/session';
|
||||
import ClientError from '@client/rest/error';
|
||||
import {Screens, Sso} from '@constants';
|
||||
import useAndroidHardwareBackHandler from '@hooks/android_back_handler';
|
||||
import useNavButtonPressed from '@hooks/navigation_button_pressed';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import Background from '@screens/background';
|
||||
import {dismissModal, popTopScreen, resetToHome} from '@screens/navigation';
|
||||
import {getFullErrorMessage, isErrorWithUrl} from '@utils/errors';
|
||||
import {logWarning} from '@utils/log';
|
||||
|
||||
import SSOWithRedirectURL from './sso_with_redirect_url';
|
||||
|
|
@ -85,15 +85,15 @@ const SSO = ({
|
|||
break;
|
||||
}
|
||||
|
||||
const onLoadEndError = (e: ClientErrorProps | Error | string) => {
|
||||
const onLoadEndError = (e: unknown) => {
|
||||
logWarning('Failed to set store from local data', e);
|
||||
if (typeof e === 'string') {
|
||||
setLoginError(e);
|
||||
return;
|
||||
}
|
||||
|
||||
let errorMessage = e.message;
|
||||
if (e instanceof ClientError && e.url) {
|
||||
let errorMessage = getFullErrorMessage(e);
|
||||
if (isErrorWithUrl(e) && e.url) {
|
||||
errorMessage += `\nURL: ${e.url}`;
|
||||
}
|
||||
setLoginError(errorMessage);
|
||||
|
|
@ -105,10 +105,10 @@ const SSO = ({
|
|||
onLoadEndError(result.error);
|
||||
return;
|
||||
}
|
||||
goToHome(result.error as never);
|
||||
goToHome(result.error);
|
||||
};
|
||||
|
||||
const goToHome = (error?: never) => {
|
||||
const goToHome = (error?: unknown) => {
|
||||
const hasError = launchError || Boolean(error);
|
||||
resetToHome({extra, launchError: hasError, launchType, serverUrl});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import FormattedText from '@components/formatted_text';
|
|||
import {Sso} from '@constants';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles';
|
||||
import {isErrorWithMessage} from '@utils/errors';
|
||||
import {isBetaApp} from '@utils/general';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
|
@ -82,9 +83,9 @@ const SSOWithRedirectURL = ({doSSOLogin, loginError, loginUrl, serverUrl, setLog
|
|||
parsedUrl.set('query', qs.stringify(query));
|
||||
const url = parsedUrl.toString();
|
||||
|
||||
const onError = (e: Error) => {
|
||||
const onError = (e: unknown) => {
|
||||
let message;
|
||||
if (e && Platform.OS === 'android' && e?.message?.match(/no activity found to handle intent/i)) {
|
||||
if (e && Platform.OS === 'android' && isErrorWithMessage(e) && e.message.match(/no activity found to handle intent/i)) {
|
||||
message = intl.formatMessage({
|
||||
id: 'mobile.oauth.failed_to_open_link_no_browser',
|
||||
defaultMessage: 'The link failed to open. Please verify that a browser is installed on the device.',
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {cleanUrlForLogging} from '@utils/url';
|
||||
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
export class ClientError extends Error {
|
||||
details: Error;
|
||||
intl?: {defaultMessage?: string; id: string} | { defaultMessage?: string; id: string } | { id: string; defaultMessage?: string; values: any } | { id: string; defaultMessage?: string };
|
||||
url: string;
|
||||
server_error_id?: string | number;
|
||||
status_code?: number;
|
||||
|
||||
constructor(baseUrl: string, data: ClientErrorProps) {
|
||||
super(`${data.message}: ${cleanUrlForLogging(baseUrl, data.url)}`);
|
||||
|
||||
this.details = data.details;
|
||||
this.intl = data.intl;
|
||||
this.message = data.message;
|
||||
this.server_error_id = data.server_error_id;
|
||||
this.status_code = data.status_code;
|
||||
this.url = data.url;
|
||||
|
||||
// Ensure message is treated as a property of this class when object spreading. Without this,
|
||||
// copying the object by using `{...error}` would not include the message.
|
||||
Object.defineProperty(this, 'message', {enumerable: true});
|
||||
}
|
||||
}
|
||||
|
||||
export const getErrorMessage = (error: Error | string, intl: IntlShape) => {
|
||||
const intlError = error as ClientError;
|
||||
if (intlError.intl) {
|
||||
return intl.formatMessage(intlError.intl);
|
||||
} else if (error instanceof Error) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
return error;
|
||||
};
|
||||
|
|
@ -2,11 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Alert} from 'react-native';
|
||||
import {
|
||||
setJSExceptionHandler,
|
||||
|
||||
// setNativeExceptionHandler
|
||||
} from 'react-native-exception-handler';
|
||||
import {setJSExceptionHandler} from 'react-native-exception-handler';
|
||||
|
||||
import {DEFAULT_LOCALE, getTranslations, t} from '@i18n';
|
||||
import {dismissAllModals, dismissAllOverlays} from '@screens/navigation';
|
||||
|
|
@ -19,8 +15,6 @@ import {
|
|||
|
||||
import {logWarning} from './log';
|
||||
|
||||
import type {ClientError} from '@utils/client_error';
|
||||
|
||||
class JavascriptAndNativeErrorHandler {
|
||||
initializeErrorHandling = () => {
|
||||
initializeSentry();
|
||||
|
|
@ -34,7 +28,7 @@ class JavascriptAndNativeErrorHandler {
|
|||
captureException(e);
|
||||
};
|
||||
|
||||
errorHandler = (e: Error | ClientError, isFatal: boolean) => {
|
||||
errorHandler = (e: unknown, isFatal: boolean) => {
|
||||
if (__DEV__ && !e && !isFatal) {
|
||||
// react-native-exception-handler redirects console.error to call this, and React calls
|
||||
// console.error without an exception when prop type validation fails, so this ends up
|
||||
|
|
|
|||
|
|
@ -1,11 +1,92 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export function isServerError(obj: unknown): obj is {server_error_id: string; message?: string} {
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
export function isServerError(obj: unknown): obj is {server_error_id?: string} {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
'server_error_id' in obj &&
|
||||
typeof obj.server_error_id === 'string'
|
||||
(
|
||||
!('server_error_id' in obj) ||
|
||||
typeof obj.server_error_id === 'string' ||
|
||||
typeof obj.server_error_id === 'undefined'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function isErrorWithMessage(obj: unknown): obj is {message: string} {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
'message' in obj &&
|
||||
typeof obj.message === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
export function isErrorWithDetails(obj: unknown): obj is {details: Error} {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
'details' in obj
|
||||
);
|
||||
}
|
||||
|
||||
export function isErrorWithIntl(obj: unknown): obj is {intl: ClientErrorIntl} {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
'intl' in obj &&
|
||||
typeof obj.intl === 'object' &&
|
||||
obj.intl !== null
|
||||
);
|
||||
}
|
||||
|
||||
export function isErrorWithStatusCode(obj: unknown): obj is {status_code: number} {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
'status_code' in obj &&
|
||||
typeof obj.status_code === 'number'
|
||||
);
|
||||
}
|
||||
|
||||
export function isErrorWithUrl(obj: unknown): obj is {url?: string} {
|
||||
return (
|
||||
typeof obj === 'object' &&
|
||||
obj !== null &&
|
||||
(
|
||||
!('url' in obj) ||
|
||||
typeof obj.url === 'string' ||
|
||||
typeof obj.url === 'undefined'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export const getFullErrorMessage = (error: unknown, intl?: IntlShape, depth = 0): string => {
|
||||
const message = getErrorMessage(error, intl);
|
||||
if (isErrorWithDetails(error)) {
|
||||
if (depth > 2) {
|
||||
return `${message}; ${getErrorMessage(error, intl)}`;
|
||||
}
|
||||
|
||||
return `${message}; ${getFullErrorMessage(error.details, intl, depth + 1)}`;
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
||||
export const getErrorMessage = (error: unknown, intl?: IntlShape) => {
|
||||
if (typeof error === 'string') {
|
||||
return error;
|
||||
}
|
||||
if (isErrorWithIntl(error)) {
|
||||
return intl ? intl.formatMessage({id: error.intl.id, defaultMessage: error.intl.defaultMessage}, error.intl.values) : error.intl.defaultMessage;
|
||||
}
|
||||
|
||||
if (isErrorWithMessage(error)) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
return 'Unknown error';
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {Alert} from 'react-native';
|
|||
import {Navigation, type Options} from 'react-native-navigation';
|
||||
|
||||
import {Screens, ServerErrors} from '@constants';
|
||||
import {isServerError} from '@utils/errors';
|
||||
import {isErrorWithMessage, isServerError} from '@utils/errors';
|
||||
|
||||
import type {AvailableScreens} from '@typings/screens/navigation';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
|
@ -85,7 +85,7 @@ export function alertTeamAddError(error: unknown, intl: IntlShape) {
|
|||
id: 'join_team.error.group_error',
|
||||
defaultMessage: 'You need to be a member of a linked group to join this team.',
|
||||
});
|
||||
} else if (error.message) {
|
||||
} else if (isErrorWithMessage(error) && error.message) {
|
||||
errMsg = error.message;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import {Platform} from 'react-native';
|
|||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import Config from '@assets/config.json';
|
||||
import ClientError from '@client/rest/error';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {getConfig} from '@queries/servers/system';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {isBetaApp} from '@utils/general';
|
||||
|
||||
import {ClientError} from './client_error';
|
||||
import {logError, logWarning} from './log';
|
||||
|
||||
import type {Database} from '@nozbe/watermelondb';
|
||||
|
|
@ -83,7 +84,7 @@ function getDsn() {
|
|||
return '';
|
||||
}
|
||||
|
||||
export function captureException(error: Error | string) {
|
||||
export function captureException(error: unknown) {
|
||||
if (!Config.SentryEnabled) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -95,7 +96,7 @@ export function captureException(error: Error | string) {
|
|||
Sentry.captureException(error);
|
||||
}
|
||||
|
||||
export function captureJSException(error: Error | ClientError, isFatal: boolean) {
|
||||
export function captureJSException(error: unknown, isFatal: boolean) {
|
||||
if (!Config.SentryEnabled) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -120,14 +121,9 @@ function captureClientErrorAsBreadcrumb(error: ClientError, isFatal: boolean) {
|
|||
isFatal: String(isFatal),
|
||||
},
|
||||
level: 'warning',
|
||||
message: getFullErrorMessage(error),
|
||||
};
|
||||
|
||||
if (error.intl?.defaultMessage) {
|
||||
breadcrumb.message = error.intl.defaultMessage;
|
||||
} else {
|
||||
breadcrumb.message = error.message;
|
||||
}
|
||||
|
||||
if (breadcrumb.data) {
|
||||
if (error.server_error_id) {
|
||||
breadcrumb.data.server_error_id = error.server_error_id;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {Alert, type AlertButton} from 'react-native';
|
|||
import CompassIcon from '@components/compass_icon';
|
||||
import {Screens, Sso, SupportedServer, Launch} from '@constants';
|
||||
import {dismissBottomSheet, showModal} from '@screens/navigation';
|
||||
import {getErrorMessage} from '@utils/client_error';
|
||||
import {getErrorMessage} from '@utils/errors';
|
||||
import {isMinimumServerVersion} from '@utils/helpers';
|
||||
import {changeOpacity} from '@utils/theme';
|
||||
import {tryOpenURL} from '@utils/url';
|
||||
|
|
@ -175,7 +175,7 @@ export async function alertServerRemove(displayName: string, onPress: () => void
|
|||
);
|
||||
}
|
||||
|
||||
export function alertServerError(intl: IntlShape, error: ClientErrorProps) {
|
||||
export function alertServerError(intl: IntlShape, error: unknown) {
|
||||
const message = getErrorMessage(error, intl);
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ export function getYouTubeVideoId(link?: string) {
|
|||
return '';
|
||||
}
|
||||
|
||||
export function tryOpenURL(url: string, onError = emptyFunction, onSuccess = emptyFunction) {
|
||||
export function tryOpenURL(url: string, onError: (error: unknown) => void = emptyFunction, onSuccess = emptyFunction) {
|
||||
Linking.openURL(url).
|
||||
then(onSuccess).
|
||||
catch(onError);
|
||||
|
|
|
|||
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -24249,7 +24249,7 @@
|
|||
},
|
||||
"@mattermost/calls": {
|
||||
"version": "git+ssh://git@github.com/mattermost/calls-common.git#d539eb36f9549075b0a0a6578174db31297c45ae",
|
||||
"from": "@mattermost/calls@git://github.com/mattermost/calls-common.git#v0.14.0"
|
||||
"from": "@mattermost/calls@github:mattermost/calls-common#v0.14.0"
|
||||
},
|
||||
"@mattermost/commonmark": {
|
||||
"version": "0.30.1-0",
|
||||
|
|
|
|||
17
types/api/client.d.ts
vendored
17
types/api/client.d.ts
vendored
|
|
@ -11,14 +11,17 @@ type ClientOptions = {
|
|||
headers?: Record<string, any>;
|
||||
};
|
||||
|
||||
interface ClientErrorProps extends Error {
|
||||
details: Error;
|
||||
intl?:
|
||||
{defaultMessage?: string; id: string; values?: Record<string, any>} |
|
||||
{ defaultMessage?: string; id: string; values?: Record<string, any> } |
|
||||
{ id: string; defaultMessage?: string; values?: Record<string, any> } |
|
||||
{ id: string; defaultMessage?: string; values?: Record<string, any> };
|
||||
type ClientErrorIntl =
|
||||
{defaultMessage?: string; id: string; values?: Record<string, any>} |
|
||||
{defaultMessage?: string; id: string; values?: Record<string, any>} |
|
||||
{id: string; defaultMessage?: string; values?: Record<string, any>} |
|
||||
{id: string; defaultMessage?: string; values?: Record<string, any>};
|
||||
|
||||
interface ClientErrorProps {
|
||||
details?: unknown;
|
||||
intl?: ClientErrorIntl;
|
||||
url: string;
|
||||
server_error_id?: string;
|
||||
status_code?: number;
|
||||
message: string;
|
||||
}
|
||||
|
|
|
|||
2
types/api/session.d.ts
vendored
2
types/api/session.d.ts
vendored
|
|
@ -14,6 +14,6 @@ interface Session {
|
|||
}
|
||||
|
||||
interface LoginActionResponse {
|
||||
error?: ClientErrorProps | Error | string;
|
||||
error?: unknown;
|
||||
failed: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import type {ClientError} from '@utils/client_error';
|
||||
|
||||
export interface jsAndNativeErrorHandler {
|
||||
interface jsAndNativeErrorHandler {
|
||||
initializeErrorHandling: () => void;
|
||||
nativeErrorHandler: (e: string) => void;
|
||||
errorHandler: (e: Error | ClientError, isFatal: boolean) => void;
|
||||
errorHandler: (e: unknown, isFatal: boolean) => void;
|
||||
}
|
||||
2
types/utils/file.d.ts
vendored
2
types/utils/file.d.ts
vendored
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
type ErrorText = Partial<ClientErrorProps> | string;
|
||||
|
||||
type ExtractedFileInfo = Partial<FileInfo> & { name: string; mime_type: string}
|
||||
|
||||
type UploadExtractedFile = (files?: ExtractedFileInfo[]) => void;
|
||||
|
|
|
|||
Loading…
Reference in a new issue