Minor performance fixes on message send (#7164)

This commit is contained in:
Daniel Espino García
2023-02-24 14:35:20 +01:00
committed by GitHub
parent ac3bd14891
commit 7c6b34afe3
9 changed files with 57 additions and 83 deletions

View File

@@ -1,58 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import DatabaseManager from '@database/manager';
import {getPostById, queryPostsInChannel, queryPostsInThread} from '@queries/servers/post';
import {logError} from '@utils/log';
export const updatePostSinceCache = async (serverUrl: string, notification: NotificationWithData) => {
try {
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
if (notification.payload?.channel_id) {
const chunks = await queryPostsInChannel(database, notification.payload.channel_id).fetch();
if (chunks.length) {
const recent = chunks[0];
const lastPost = await getPostById(database, notification.payload.post_id);
if (lastPost) {
await operator.database.write(async () => {
await recent.update(() => {
recent.latest = lastPost.createAt;
});
});
}
}
}
return {};
} catch (error) {
logError('Failed updatePostSinceCache', error);
return {error};
}
};
export const updatePostsInThreadsSinceCache = async (serverUrl: string, notification: NotificationWithData) => {
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
if (!operator) {
return {error: `${serverUrl} database not found`};
}
try {
if (notification.payload?.root_id) {
const {database} = operator;
const chunks = await queryPostsInThread(database, notification.payload.root_id).fetch();
if (chunks.length) {
const recent = chunks[0];
const lastPost = await getPostById(database, notification.payload.post_id);
if (lastPost) {
await operator.database.write(async () => {
await recent.update(() => {
recent.latest = lastPost.createAt;
});
});
}
}
}
return {};
} catch (error) {
return {error};
}
};

View File

@@ -19,21 +19,25 @@ import PostList from './post_list';
import type {WithDatabaseArgs} from '@typings/database/database';
import type PostModel from '@typings/database/models/servers/post';
const enhanced = withObservables(['posts'], ({database, posts}: {posts: PostModel[]} & WithDatabaseArgs) => {
const enhancedWithoutPosts = withObservables([], ({database}: WithDatabaseArgs) => {
const currentUser = observeCurrentUser(database);
const postIds = posts.map((p) => p.id);
return {
appsEnabled: observeConfigBooleanValue(database, 'FeatureFlagAppsEnabled'),
isTimezoneEnabled: observeConfigBooleanValue(database, 'ExperimentalTimezone'),
currentTimezone: currentUser.pipe((switchMap((user) => of$(getTimezone(user?.timezone || null))))),
currentUserId: currentUser.pipe((switchMap((user) => of$(user?.id)))),
currentUsername: currentUser.pipe((switchMap((user) => of$(user?.username)))),
savedPostIds: observeSavedPostsByIds(database, postIds),
customEmojiNames: queryAllCustomEmojis(database).observe().pipe(
customEmojiNames: queryAllCustomEmojis(database).observeWithColumns(['name']).pipe(
switchMap((customEmojis) => of$(mapCustomEmojiNames(customEmojis))),
),
};
});
export default React.memo(withDatabase(enhanced(PostList)));
const enhanced = withObservables(['posts'], ({database, posts}: {posts: PostModel[]} & WithDatabaseArgs) => {
const postIds = posts.map((p) => p.id);
return {
savedPostIds: observeSavedPostsByIds(database, postIds),
};
});
export default React.memo(withDatabase(enhancedWithoutPosts(enhanced(PostList))));

View File

@@ -3,8 +3,9 @@
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import React from 'react';
import {of as of$, first as first$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {distinctUntilChanged, switchMap} from 'rxjs/operators';
import {observeMyChannel} from '@queries/servers/channel';
import {observeThreadById} from '@queries/servers/thread';
@@ -31,8 +32,14 @@ const enhanced = withObservables(['channelId', 'isCRTEnabled', 'rootId'], ({chan
}
const myChannel = observeMyChannel(database, channelId);
const isManualUnread = myChannel.pipe(switchMap((ch) => of$(ch?.manuallyUnread)));
const unreadCount = myChannel.pipe(switchMap((ch) => of$(ch?.messageCount)));
const isManualUnread = myChannel.pipe(
switchMap((ch) => of$(ch?.manuallyUnread)),
distinctUntilChanged(),
);
const unreadCount = myChannel.pipe(
switchMap((ch) => of$(ch?.messageCount)),
distinctUntilChanged(),
);
return {
isManualUnread,
@@ -40,4 +47,4 @@ const enhanced = withObservables(['channelId', 'isCRTEnabled', 'rootId'], ({chan
};
});
export default withDatabase(enhanced(MoreMessages));
export default React.memo(withDatabase(enhanced(MoreMessages)));

View File

@@ -211,6 +211,13 @@ export const observeMyChannel = (database: Database, channelId: string) => {
);
};
export const observeMyChannelRoles = (database: Database, channelId: string) => {
return observeMyChannel(database, channelId).pipe(
switchMap((v) => of$(v?.roles)),
distinctUntilChanged(),
);
};
export const getChannelById = async (database: Database, channelId: string) => {
try {
const channel = await database.get<ChannelModel>(CHANNEL).find(channelId);

View File

@@ -9,8 +9,8 @@ import {Database as DatabaseConstants, General, Permissions} from '@constants';
import {isDMorGM} from '@utils/channel';
import {hasPermission} from '@utils/role';
import {observeChannel, observeMyChannel} from './channel';
import {observeMyTeam} from './team';
import {observeChannel, observeMyChannelRoles} from './channel';
import {observeMyTeam, observeMyTeamRoles} from './team';
import type ChannelModel from '@typings/database/models/servers/channel';
import type PostModel from '@typings/database/models/servers/post';
@@ -41,16 +41,16 @@ export function observePermissionForChannel(database: Database, channel: Channel
if (!user || !channel) {
return of$(defaultValue);
}
const myChannel = observeMyChannel(database, channel.id);
const myTeam = channel.teamId ? observeMyTeam(database, channel.teamId) : of$(undefined);
const myChannelRoles = observeMyChannelRoles(database, channel.id);
const myTeamRoles = channel.teamId ? observeMyTeamRoles(database, channel.teamId) : of$(undefined);
return combineLatest([myChannel, myTeam]).pipe(switchMap(([mc, mt]) => {
return combineLatest([myChannelRoles, myTeamRoles]).pipe(switchMap(([mc, mt]) => {
const rolesArray = [...user.roles.split(' ')];
if (mc) {
rolesArray.push(...mc.roles.split(' '));
rolesArray.push(...mc.split(' '));
}
if (mt) {
rolesArray.push(...mt.roles.split(' '));
rolesArray.push(...mt.split(' '));
}
return queryRolesByNames(database, rolesArray).observeWithColumns(['permissions']).pipe(
switchMap((r) => of$(hasPermission(r, permission))),

View File

@@ -296,6 +296,13 @@ export const observeMyTeam = (database: Database, teamId: string) => {
);
};
export const observeMyTeamRoles = (database: Database, teamId: string) => {
return observeMyTeam(database, teamId).pipe(
switchMap((v) => of$(v?.roles)),
distinctUntilChanged(),
);
};
export const getTeamById = async (database: Database, teamId: string) => {
try {
const team = (await database.get<TeamModel>(TEAM).find(teamId));

View File

@@ -48,6 +48,13 @@ export const observeCurrentUser = (database: Database) => {
);
};
export const observeCurrentUserRoles = (database: Database) => {
return observeCurrentUser(database).pipe(
switchMap((v) => of$(v?.roles)),
distinctUntilChanged(),
);
};
export const queryAllUsers = (database: Database) => {
return database.get<UserModel>(USER).query();
};

View File

@@ -6,9 +6,9 @@ import withObservables from '@nozbe/with-observables';
import {combineLatest} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {observeChannel, observeMyChannel} from '@queries/servers/channel';
import {observeChannel, observeMyChannelRoles} from '@queries/servers/channel';
import {queryRolesByNames} from '@queries/servers/role';
import {observeCurrentUser} from '@queries/servers/user';
import {observeCurrentUserRoles} from '@queries/servers/user';
import Intro from './intro';
@@ -16,13 +16,13 @@ import type {WithDatabaseArgs} from '@typings/database/database';
const enhanced = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => {
const channel = observeChannel(database, channelId);
const myChannel = observeMyChannel(database, channelId);
const me = observeCurrentUser(database);
const myChannelRoles = observeMyChannelRoles(database, channelId);
const meRoles = observeCurrentUserRoles(database);
const roles = combineLatest([me, myChannel]).pipe(
const roles = combineLatest([meRoles, myChannelRoles]).pipe(
switchMap(([user, member]) => {
const userRoles = user?.roles.split(' ');
const memberRoles = member?.roles.split(' ');
const userRoles = user?.split(' ');
const memberRoles = member?.split(' ');
const combinedRoles = [];
if (userRoles) {
combinedRoles.push(...userRoles);

View File

@@ -17,7 +17,6 @@ import {
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
import {useInputPropagation} from '@app/hooks/input';
import Autocomplete from '@components/autocomplete';
import ErrorText from '@components/error_text';
import FloatingTextInput from '@components/floating_text_input_label';
@@ -28,6 +27,7 @@ import {General, Channel} from '@constants';
import {useTheme} from '@context/theme';
import {useAutocompleteDefaultAnimatedValues} from '@hooks/autocomplete';
import {useIsTablet, useKeyboardHeight, useModalPosition} from '@hooks/device';
import {useInputPropagation} from '@hooks/input';
import {t} from '@i18n';
import {
changeOpacity,