MM-49393 Remove more code from utils.tsx (#24266)

* Remove unused Utils.scrollbarWidth

* Remove pointless checkAndSetMobileView action

* Fix CommentedOn using un-connected version of UserProfile component

* Turn Utils.getMenuItemIcon into ActionsMenuIcon component

* Remove Utils.isPostEphemeral in favour of mattermost-redux version

* Remove Utils.getRootId and Utils.getRootPost

* Move Utils.compareChannels into ChannelSelectorModal

* Address feedback

* Revert "Fix CommentedOn using un-connected version of UserProfile component"

This reverts commit bdd113ee95.
This commit is contained in:
Harrison Healey 2023-09-01 11:56:23 -04:00 committed by GitHub
parent 4f0f3845e4
commit 47e18ea829
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 51 additions and 83 deletions

View File

@ -57,21 +57,10 @@ import {getSelectedPost, getSelectedPostId} from 'selectors/rhs';
import {getHistory} from 'utils/browser_history';
import {Constants, ActionTypes, EventTypes, PostRequestTypes} from 'utils/constants';
import {isMobile} from 'utils/utils';
import LocalStorageStore from 'stores/local_storage_store';
import {isArchivedChannel} from 'utils/channel_utils';
import type {GlobalState} from 'types/store';
export function checkAndSetMobileView() {
return (dispatch: DispatchFunc) => {
dispatch({
type: ActionTypes.UPDATE_MOBILE_VIEW,
data: isMobile(),
});
return {data: true};
};
}
export function goToLastViewedChannel() {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
const state = getState();

View File

@ -26,7 +26,6 @@ import {Post} from '@mattermost/types/posts';
import {trackEvent} from 'actions/telemetry_actions.jsx';
import {getSearchTerms, getRhsState, getPluggableId, getFilesSearchExtFilter, getPreviousRhsState} from 'selectors/rhs';
import {ActionTypes, RHSStates, Constants} from 'utils/constants';
import * as Utils from 'utils/utils';
import {getBrowserUtcOffset, getUtcOffsetForTimeZone} from 'utils/timezone';
import {RhsState} from 'types/store/rhs';
import {GlobalState} from 'types/store';
@ -37,7 +36,7 @@ import {SidebarSize} from 'components/resizable_sidebar/constants';
function selectPostFromRightHandSideSearchWithPreviousState(post: Post, previousRhsState?: RhsState) {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
const postRootId = Utils.getRootId(post);
const postRootId = post.root_id || post.id;
await dispatch(PostActions.getPostThread(postRootId));
const state = getState() as GlobalState;

View File

@ -137,8 +137,8 @@ exports[`components/actions_menu/ActionsMenu has actions - marketplace enabled a
/>
<MenuItemAction
icon={
<span
className="icon-view-grid-plus-outline MenuItem__compass-icon"
<ActionsMenuIcon
name="icon-view-grid-plus-outline"
/>
}
id="marketplace_icon_post_id_1"
@ -230,8 +230,8 @@ exports[`components/actions_menu/ActionsMenu no actions - sysadmin - menu should
id="marketPlaceButton"
onClick={[Function]}
>
<span
className="icon-view-grid-plus-outline visit-marketplace-button-icon MenuItem__compass-icon"
<ActionsMenuIcon
name="icon-view-grid-plus-outline visit-marketplace-button-icon"
/>
<span
className="visit-marketplace-button-text"

View File

@ -29,6 +29,8 @@ import MenuWrapper from 'components/widgets/menu/menu_wrapper';
import {PluginComponent} from 'types/store/plugins';
import {createCallContext} from 'utils/apps';
import {ActionsMenuIcon} from './actions_menu_icon';
const MENU_BOTTOM_MARGIN = 80;
export const PLUGGABLE_COMPONENT = 'PostDropdownMenuItem';
@ -217,7 +219,7 @@ export class ActionMenuClass extends React.PureComponent<Props, State> {
className='btn btn-primary visit-marketplace-button'
onClick={this.handleOpenMarketplace}
>
{Utils.getMenuItemIcon('icon-view-grid-plus-outline visit-marketplace-button-icon')}
<ActionsMenuIcon name='icon-view-grid-plus-outline visit-marketplace-button-icon'/>
<span className='visit-marketplace-button-text'>
<FormattedMarkdownMessage
id='post_info.actions.visitMarketplace'
@ -339,7 +341,7 @@ export class ActionMenuClass extends React.PureComponent<Props, State> {
key={`marketplace_${this.props.post.id}`}
show={true}
text={formatMessage({id: 'post_info.marketplace', defaultMessage: 'App Marketplace'})}
icon={Utils.getMenuItemIcon('icon-view-grid-plus-outline')}
icon={<ActionsMenuIcon name='icon-view-grid-plus-outline'/>}
onClick={this.handleOpenMarketplace}
/>
</React.Fragment>

View File

@ -0,0 +1,16 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
type Props = {
name: string;
dangerous?: boolean;
}
export function ActionsMenuIcon({name, dangerous}: Props) {
const colorClass = dangerous ? 'MenuItem__compass-icon-dangerous' : 'MenuItem__compass-icon';
return (
<span className={`${name} ${colorClass}`}/>
);
}

View File

@ -5,12 +5,12 @@ import React from 'react';
import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import {ChannelSearchOpts, ChannelWithTeamData} from '@mattermost/types/channels';
import {Channel, ChannelSearchOpts, ChannelWithTeamData} from '@mattermost/types/channels';
import {ActionResult} from 'mattermost-redux/types/actions';
import Constants from 'utils/constants';
import {localizeMessage, compareChannels} from 'utils/utils';
import {localizeMessage} from 'utils/utils';
import MultiSelect, {Value} from 'components/multiselect/multiselect';
@ -265,3 +265,16 @@ export default class ChannelSelectorModal extends React.PureComponent<Props, Sta
);
}
}
function compareChannels(a: Channel, b: Channel) {
const aDisplayName = a.display_name.toUpperCase();
const bDisplayName = b.display_name.toUpperCase();
const result = aDisplayName.localeCompare(bDisplayName);
if (result !== 0) {
return result;
}
const aName = a.name.toUpperCase();
const bName = b.name.toUpperCase();
return aName.localeCompare(bName);
}

View File

@ -477,6 +477,11 @@ const EditPost = ({editingPost, actions, canEditPost, config, channelId, draft,
);
}
let rootId = '';
if (editingPost.post) {
rootId = editingPost.post.root_id || editingPost.post.id;
}
return (
<div
className={classNames('post--editing__wrapper', {
@ -486,7 +491,7 @@ const EditPost = ({editingPost, actions, canEditPost, config, channelId, draft,
>
<Textbox
tabIndex={0}
rootId={editingPost.post ? Utils.getRootId(editingPost.post) : ''}
rootId={rootId}
onChange={handleChange}
onKeyPress={handleEditKeyPress}
onKeyDown={handleKeyDown}

View File

@ -5,8 +5,8 @@ import React, {ReactNode} from 'react';
import {FormattedDate, FormattedMessage, FormattedTime} from 'react-intl';
import {General, Posts} from 'mattermost-redux/constants';
import {isPostEphemeral} from 'mattermost-redux/utils/post_utils';
import * as Utils from 'utils/utils';
import {TextFormattingOptions} from 'utils/text_formatting';
import {getSiteURL} from 'utils/url';
import Markdown from 'components/markdown';
@ -387,7 +387,7 @@ const systemMessageRenderers = {
};
export function renderSystemMessage(post: Post, currentTeam: Team, channel: Channel, hideGuestTags: boolean, isUserCanManageMembers?: boolean, isMilitaryTime?: boolean, timezone?: string): ReactNode {
const isEphemeral = Utils.isPostEphemeral(post);
const isEphemeral = isPostEphemeral(post);
if (isEphemeral && post.props?.type === Posts.POST_TYPES.REMINDER) {
return renderReminderACKMessage(post, currentTeam, Boolean(isMilitaryTime), timezone);
}

View File

@ -17,7 +17,6 @@ exports[`components/post_view/post_list snapshot for loading when there are no p
Object {
"canLoadMorePosts": [Function],
"changeUnreadChunkTimeStamp": [MockFunction],
"checkAndSetMobileView": [MockFunction],
"loadNewerPosts": [Function],
"loadOlderPosts": [Function],
"toggleShouldStartFromBottomWhenUnread": [MockFunction],
@ -56,7 +55,6 @@ exports[`components/post_view/post_list snapshot with couple of posts 1`] = `
Object {
"canLoadMorePosts": [Function],
"changeUnreadChunkTimeStamp": [MockFunction],
"checkAndSetMobileView": [MockFunction],
"loadNewerPosts": [Function],
"loadOlderPosts": [Function],
"toggleShouldStartFromBottomWhenUnread": [MockFunction],

View File

@ -14,7 +14,6 @@ import {RequestStatus} from 'mattermost-redux/constants';
import {updateNewMessagesAtInChannel} from 'actions/global_actions';
import {getLatestPostId} from 'utils/post_utils';
import {
checkAndSetMobileView,
loadPosts,
loadUnreads,
loadPostsAround,
@ -112,7 +111,6 @@ function mapDispatchToProps(dispatch: Dispatch) {
loadPosts,
loadLatestPosts,
loadPostsAround,
checkAndSetMobileView,
syncPostsInChannel,
markChannelAsRead,
updateNewMessagesAtInChannel,

View File

@ -16,7 +16,6 @@ const actionsProp = {
loadPosts: jest.fn().mockImplementation(() => Promise.resolve({moreToLoad: false})),
syncPostsInChannel: jest.fn().mockResolvedValue({}),
loadLatestPosts: jest.fn().mockImplementation(() => Promise.resolve({atLatestMessage: true, atOldestmessage: true})),
checkAndSetMobileView: jest.fn(),
markChannelAsRead: jest.fn(),
updateNewMessagesAtInChannel: jest.fn(),
toggleShouldStartFromBottomWhenUnread: jest.fn(),

View File

@ -125,11 +125,6 @@ export interface Props {
*/
loadPosts: (parameters: LoadPostsParameters) => Promise<LoadPostsReturnValue>;
/*
* Used to set mobile view on resize
*/
checkAndSetMobileView: () => Promise<void>;
/*
* Used to loading posts since a timestamp to sync the posts
*/
@ -157,7 +152,6 @@ export default class PostList extends React.PureComponent<Props, State> {
private actionsForPostList: {
loadOlderPosts: () => Promise<void>;
loadNewerPosts: () => Promise<void>;
checkAndSetMobileView: () => void;
canLoadMorePosts: (type: CanLoadMorePosts) => Promise<void>;
changeUnreadChunkTimeStamp: (lastViewedAt: number) => void;
updateNewMessagesAtInChannel: typeof updateNewMessagesAtInChannel;
@ -182,7 +176,6 @@ export default class PostList extends React.PureComponent<Props, State> {
this.actionsForPostList = {
loadOlderPosts: this.getPostsBefore,
loadNewerPosts: this.getPostsAfter,
checkAndSetMobileView: props.actions.checkAndSetMobileView,
canLoadMorePosts: this.canLoadMorePosts,
changeUnreadChunkTimeStamp: props.changeUnreadChunkTimeStamp,
toggleShouldStartFromBottomWhenUnread: props.toggleShouldStartFromBottomWhenUnread,

View File

@ -16,7 +16,6 @@ import PostList from './post_list_virtualized';
describe('PostList', () => {
const baseActions = {
checkAndSetMobileView: jest.fn(),
loadOlderPosts: jest.fn(),
loadNewerPosts: jest.fn(),
canLoadMorePosts: jest.fn(),

View File

@ -112,11 +112,6 @@ type Props = {
*/
canLoadMorePosts: (type: CanLoadMorePosts) => Promise<void>;
/*
* Function to check and set if app is in mobile view
*/
checkAndSetMobileView: () => void;
/*
* Function to change the post selected for postList
*/
@ -208,7 +203,6 @@ export default class PostList extends React.PureComponent<Props, State> {
componentDidMount() {
this.mounted = true;
this.props.actions.checkAndSetMobileView();
window.addEventListener('resize', this.handleWindowResize);
EventEmitter.addListener(EventTypes.POST_LIST_SCROLL_TO_BOTTOM, this.scrollToLatestMessages);
@ -318,7 +312,6 @@ export default class PostList extends React.PureComponent<Props, State> {
};
handleWindowResize = () => {
this.props.actions.checkAndSetMobileView();
this.showSearchHintThreshold = this.getShowSearchHintThreshold();
};

View File

@ -8,6 +8,7 @@ import {Posts} from 'mattermost-redux/constants';
import {Post} from '@mattermost/types/posts';
import {Theme} from 'mattermost-redux/selectors/entities/preferences';
import {isPostEphemeral} from 'mattermost-redux/utils/post_utils';
import * as Utils from 'utils/utils';
@ -129,7 +130,7 @@ export default class PostMessageView extends React.PureComponent<Props, State> {
}
let message = post.message;
const isEphemeral = Utils.isPostEphemeral(post);
const isEphemeral = isPostEphemeral(post);
if (compactDisplay && isEphemeral) {
const visibleMessage = Utils.localizeMessage('post_info.message.visible.compact', ' (Only visible to you)');
message = message.concat(visibleMessage);

View File

@ -25,7 +25,7 @@ import {
import {getPost as getPostAction} from 'mattermost-redux/actions/posts';
import {getTeamByName as getTeamByNameAction} from 'mattermost-redux/actions/teams';
import {Client4} from 'mattermost-redux/client';
import {Posts, Preferences, General} from 'mattermost-redux/constants';
import {Preferences, General} from 'mattermost-redux/constants';
import {
getChannel,
getChannelsNameMapInTeam,
@ -56,7 +56,6 @@ import {getIsMobileView} from 'selectors/views/browser';
import {FileInfo} from '@mattermost/types/files';
import {Team} from '@mattermost/types/teams';
import {Post} from '@mattermost/types/posts';
import {UserProfile} from '@mattermost/types/users';
import {Channel} from '@mattermost/types/channels';
@ -309,13 +308,6 @@ export function getIconClassName(fileTypeIn: string) {
return 'generic';
}
export function getMenuItemIcon(name: string, dangerous?: boolean) {
const colorClass = dangerous ? 'MenuItem__compass-icon-dangerous' : 'MenuItem__compass-icon';
return (
<span className={`${name} ${colorClass}`}/>
);
}
export function toTitleCase(str: string): string {
function doTitleCase(txt: string) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
@ -851,10 +843,6 @@ export function setCaretPosition(input: HTMLInputElement, pos: number) {
setSelectionRange(input, pos, pos);
}
export function scrollbarWidth(el: HTMLElement) {
return el.offsetWidth - el.clientWidth;
}
export function isValidUsername(name: string) {
let error;
if (!name) {
@ -1231,18 +1219,6 @@ export function clearFileInput(elm: HTMLInputElement) {
}
}
export function isPostEphemeral(post: Post) {
return post.type === Constants.PostTypes.EPHEMERAL || post.state === Posts.POST_DELETED;
}
export function getRootId(post: Post) {
return post.root_id === '' ? post.id : post.root_id;
}
export function getRootPost(postList: Post[]) {
return postList.find((post) => post.root_id === '');
}
export function localizeMessage(id: string, defaultMessage?: string) {
const state = store.getState();
@ -1545,19 +1521,6 @@ export function moveCursorToEnd(e: React.MouseEvent | React.FocusEvent) {
}
}
export function compareChannels(a: Channel, b: Channel) {
const aDisplayName = a.display_name.toUpperCase();
const bDisplayName = b.display_name.toUpperCase();
const result = aDisplayName.localeCompare(bDisplayName);
if (result !== 0) {
return result;
}
const aName = a.name.toUpperCase();
const bName = b.name.toUpperCase();
return aName.localeCompare(bName);
}
export function setCSRFFromCookie() {
if (typeof document !== 'undefined' && typeof document.cookie !== 'undefined') {
const cookies = document.cookie.split(';');