Skip to content

Commit

Permalink
[MM-54493] Allow a user to disable the webapp prefetch (mattermost#24389
Browse files Browse the repository at this point in the history
)

* allow a user to disable the webapp prefetch if they are experiencing degraded performance on initial load
---------
Co-authored-by: Mattermost Build <[email protected]>
  • Loading branch information
BenCookie95 authored Oct 2, 2023
1 parent 460fa05 commit 9bbdca7
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ describe('/components/data_prefetch', () => {
last_post_at: 1235,
last_root_post_at: 1235,
})],
disableWebappPrefetchAllowed: false,
dataPrefetchEnabled: true,
};

beforeEach(() => {
Expand Down
14 changes: 11 additions & 3 deletions webapp/channels/src/components/data_prefetch/data_prefetch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ type Props = {
sidebarLoaded: boolean;

unreadChannels: Channel[];

disableWebappPrefetchAllowed: boolean;
dataPrefetchEnabled: boolean;
actions: {
prefetchChannelPosts: (channelId: string, delay?: number) => Promise<any>;
trackPreloadedChannels: (prefetchQueueObj: Record<string, string[]>) => void;
Expand Down Expand Up @@ -52,15 +55,20 @@ export default class DataPrefetch extends React.PureComponent<Props> {
private prefetchTimeout?: number;

async componentDidUpdate(prevProps: Props) {
const {currentChannelId, prefetchQueueObj, sidebarLoaded} = this.props;
const {currentChannelId, prefetchQueueObj, sidebarLoaded, disableWebappPrefetchAllowed, dataPrefetchEnabled} = this.props;
const enablePrefetch = (!disableWebappPrefetchAllowed) || (disableWebappPrefetchAllowed && dataPrefetchEnabled);
if (currentChannelId && sidebarLoaded && (!prevProps.currentChannelId || !prevProps.sidebarLoaded)) {
queue.add(async () => this.prefetchPosts(currentChannelId));
await loadProfilesForSidebar();
this.prefetchData();
if (enablePrefetch) {
this.prefetchData();
}
} else if (prevProps.prefetchQueueObj !== prefetchQueueObj) {
clearTimeout(this.prefetchTimeout);
await queue.clear();
this.prefetchData();
if (enablePrefetch) {
this.prefetchData();
}
}

if (currentChannelId && sidebarLoaded && (!prevProps.currentChannelId || !prevProps.sidebarLoaded)) {
Expand Down
7 changes: 6 additions & 1 deletion webapp/channels/src/components/data_prefetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import type {Channel, ChannelMembership} from '@mattermost/types/channels';
import type {PostList} from '@mattermost/types/posts';
import type {RelationOneToOne} from '@mattermost/types/utilities';

import {Preferences} from 'mattermost-redux/constants';
import {getCurrentChannelId, getUnreadChannels} from 'mattermost-redux/selectors/entities/channels';
import {getMyChannelMemberships} from 'mattermost-redux/selectors/entities/common';
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {isPerformanceDebuggingEnabled} from 'mattermost-redux/selectors/entities/general';
import {getBool, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {isChannelMuted} from 'mattermost-redux/utils/channel_utils';
import {memoizeResult} from 'mattermost-redux/utils/helpers';

Expand Down Expand Up @@ -82,13 +84,16 @@ function mapStateToProps(state: GlobalState) {
const unreadChannels = getUnreadChannels(state, lastUnreadChannel);
const prefetchQueueObj = prefetchQueue(unreadChannels, memberships, isCollapsedThreadsEnabled(state));
const prefetchRequestStatus = state.views.channel.channelPrefetchStatus;
const disableWebappPrefetchAllowed = isPerformanceDebuggingEnabled(state);

return {
currentChannelId: getCurrentChannelId(state),
prefetchQueueObj,
prefetchRequestStatus,
sidebarLoaded: isSidebarLoaded(state),
unreadChannels,
disableWebappPrefetchAllowed,
dataPrefetchEnabled: getBool(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_DATA_PREFETCH, true),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {ActionCreatorsMapObject, Dispatch} from 'redux';

import {savePreferences} from 'mattermost-redux/actions/preferences';
import {updateUserActive, revokeAllSessionsForUser} from 'mattermost-redux/actions/users';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selectors/entities/general';
import {get, getUnreadScrollPositionPreference, makeGetCategory, syncedDraftsAreAllowed} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import type {ActionFunc} from 'mattermost-redux/types/actions';
Expand All @@ -27,6 +27,7 @@ function makeMapStateToProps() {

const enablePreviewFeatures = config.EnablePreviewFeatures === 'true';
const enableUserDeactivation = config.EnableUserDeactivation === 'true';
const disableWebappPrefetchAllowed = isPerformanceDebuggingEnabled(state);
const enableJoinLeaveMessage = config.EnableJoinLeaveMessageByDefault === 'true';

return {
Expand All @@ -41,6 +42,8 @@ function makeMapStateToProps() {
enablePreviewFeatures,
enableUserDeactivation,
syncedDraftsAreAllowed: syncedDraftsAreAllowed(state),
disableWebappPrefetchAllowed,
dataPrefetchEnabled: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'data_prefetch', 'true'),
};
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ describe('components/user_settings/display/UserSettingsDisplay', () => {
enablePreviewFeatures: false,
enableUserDeactivation: false,
syncedDraftsAreAllowed: true,
disableWebappPrefetchAllowed: false,
dataPrefetchEnabled: 'true',
};

test('should have called handleSubmit', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Settings = {
formatting: Props['formatting'];
join_leave: Props['joinLeave'];
sync_drafts: Props['syncDrafts'];
data_prefetch: Props['dataPrefetchEnabled'];
};

export type Props = {
Expand All @@ -54,6 +55,8 @@ export type Props = {
enablePreviewFeatures: boolean;
enableUserDeactivation: boolean;
syncedDraftsAreAllowed: boolean;
disableWebappPrefetchAllowed: boolean;
dataPrefetchEnabled: string;
actions: {
savePreferences: (userId: string, preferences: PreferenceType[]) => Promise<ActionResult>;
updateUserActive: (userId: string, active: boolean) => Promise<ActionResult>;
Expand Down Expand Up @@ -87,6 +90,7 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
formatting: this.props.formatting,
join_leave: this.props.joinLeave,
sync_drafts: this.props.syncDrafts,
data_prefetch: this.props.dataPrefetchEnabled,
[Preferences.UNREAD_SCROLL_POSITION]: this.props.unreadScrollPosition,
};

Expand Down Expand Up @@ -575,6 +579,93 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
);
};

renderDataPrefetchSection = () => {
const active = this.props.activeSection === AdvancedSections.DATA_PREFETCH;
let max = null;
if (active) {
max = (
<SettingItemMax
title={
<FormattedMessage
id='user.settings.advance.dataPrefetch.Title'
defaultMessage='Allow Mattermost to prefetch channel posts'
/>
}
inputs={[
<fieldset key='syncDraftsSetting'>
<legend className='form-legend hidden-label'>
<FormattedMessage
id='user.settings.advance.dataPrefetch.Title'
defaultMessage='Allow Mattermost to prefetch channel posts'
/>
</legend>
<div className='radio'>
<label>
<input
id='dataPrefetchOn'
type='radio'
name='dataPrefetch'
checked={this.state.settings.data_prefetch !== 'false'}
onChange={this.updateSetting.bind(this, 'data_prefetch', 'true')}
/>
<FormattedMessage
id='user.settings.advance.on'
defaultMessage='On'
/>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
id='dataPrefetchOff'
type='radio'
name='dataPrefetch'
checked={this.state.settings.data_prefetch === 'false'}
onChange={this.updateSetting.bind(this, 'data_prefetch', 'false')}
/>
<FormattedMessage
id='user.settings.advance.off'
defaultMessage='Off'
/>
</label>
<br/>
</div>
<div className='mt-5'>
<FormattedMessage
id='user.settings.advance.dataPrefetch.Desc'
defaultMessage='When disabled, messages and user information will be fetched on each channel load instead of being pre-fetched on startup. Disabling prefetch is recommended for users with a high unread channel count in order to improve application performance.'
/>
</div>
</fieldset>,
]}
setting={AdvancedSections.DATA_PREFETCH}
submit={this.handleSubmit.bind(this, ['data_prefetch'])}
saving={this.state.isSaving}
serverError={this.state.serverError}
updateSection={this.handleUpdateSection}
/>
);
}

return (
<SettingItem
active={active}
areAllSectionsInactive={this.props.activeSection === ''}
title={
<FormattedMessage
id='user.settings.advance.dataPrefetch.Title'
defaultMessage='Allow Mattermost to prefetch channel posts'
/>
}
describe={this.renderOnOffLabel(this.state.settings.data_prefetch)}
section={AdvancedSections.DATA_PREFETCH}
updateSection={this.handleUpdateSection}
max={max}
/>
);
};

renderFeatureLabel(feature: string): ReactNode {
switch (feature) {
case 'MARKDOWN_PREVIEW':
Expand Down Expand Up @@ -895,6 +986,15 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
}
}

let dataPrefetchSection = null;
let dataPrefetchSectionDivider = null;
if (this.props.disableWebappPrefetchAllowed) {
dataPrefetchSection = this.renderDataPrefetchSection();
if (syncDraftsSection) {
dataPrefetchSectionDivider = <div className='divider-light'/>;
}
}

return (
<div>
<div className='modal-header'>
Expand Down Expand Up @@ -953,6 +1053,8 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
{unreadScrollPositionSection}
{syncDraftsSectionDivider}
{syncDraftsSection}
{dataPrefetchSectionDivider}
{dataPrefetchSection}
<div className='divider-dark'/>
{makeConfirmationModal}
</div>
Expand Down
2 changes: 2 additions & 0 deletions webapp/channels/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5208,6 +5208,8 @@
"user_profile.send.dm.yourself": "Send yourself a message",
"user.settings.advance.confirmDeactivateAccountTitle": "Confirm Deactivation",
"user.settings.advance.confirmDeactivateDesc": "Are you sure you want to deactivate your account? This can only be reversed by your System Administrator.",
"user.settings.advance.dataPrefetch.Desc": "When disabled, messages and user information will be fetched on each channel load instead of being pre-fetched on startup. Disabling prefetch is recommended for users with a high unread channel count in order to improve application performance.",
"user.settings.advance.dataPrefetch.Title": "Allow Mattermost to prefetch channel posts",
"user.settings.advance.deactivate_member_modal.deactivateButton": "Yes, deactivate my account",
"user.settings.advance.deactivateAccountTitle": "Deactivate Account",
"user.settings.advance.deactivateDesc": "Deactivating your account removes your ability to log in to this server and disables all email and mobile notifications. To reactivate your account, contact your System Administrator.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const Preferences = {
ADVANCED_CODE_BLOCK_ON_CTRL_ENTER: 'code_block_ctrl_enter',
ADVANCED_SEND_ON_CTRL_ENTER: 'send_on_ctrl_enter',
ADVANCED_SYNC_DRAFTS: 'sync_drafts',
ADVANCED_DATA_PREFETCH: 'data_prefetch',
CATEGORY_WHATS_NEW_MODAL: 'whats_new_modal',
HAS_SEEN_SIDEBAR_WHATS_NEW_MODAL: 'has_seen_sidebar_whats_new_modal',

Expand Down
1 change: 1 addition & 0 deletions webapp/channels/src/utils/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,7 @@ export const AdvancedSections = {
PREVIEW_FEATURES: 'advancedPreviewFeatures',
PERFORMANCE_DEBUGGING: 'performanceDebugging',
SYNC_DRAFTS: 'syncDrafts',
DATA_PREFETCH: 'dataPrefetch',
};

export const RHSStates = {
Expand Down

0 comments on commit 9bbdca7

Please sign in to comment.