mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
MM-49393 Remove Utils.isMobile (#24271)
* Switch Utils.isMobile to getIsMobileView in most places * Copy Utils.isMobile into menu widgets * Actually remove Utils.isMobile * Remove pointless checkAndSetMobileView action * Fix incorrect import of UserProfile * Fix unit test
This commit is contained in:
parent
47e18ea829
commit
b17daf79b1
@ -273,8 +273,6 @@ export class ActionMenuClass extends React.PureComponent<Props, State> {
|
||||
return null;
|
||||
}
|
||||
|
||||
// const isMobile = this.props.isMobileView TODO;
|
||||
|
||||
const pluginItems = this.props.pluginMenuItems?.
|
||||
filter((item) => {
|
||||
return item.filter ? item.filter(this.props.post.id) : item;
|
||||
|
@ -15,10 +15,9 @@ import {ActionFunc} from 'mattermost-redux/types/actions';
|
||||
|
||||
import {GlobalState} from 'types/store';
|
||||
|
||||
import {isMobile} from 'utils/utils';
|
||||
|
||||
import {getNavigationBlocked} from 'selectors/views/admin';
|
||||
import {getAdminDefinition, getConsoleAccess} from 'selectors/admin_console';
|
||||
import {getNavigationBlocked} from 'selectors/views/admin';
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import {OnboardingTaskCategory, OnboardingTaskList} from 'components/onboarding_tasks';
|
||||
|
||||
@ -33,7 +32,7 @@ function mapStateToProps(state: GlobalState) {
|
||||
const consoleAccess = getConsoleAccess(state);
|
||||
const taskListStatus = getBool(state, OnboardingTaskCategory, OnboardingTaskList.ONBOARDING_TASK_LIST_SHOW);
|
||||
const isUserFirstAdmin = isFirstAdmin(state);
|
||||
const isMobileView = isMobile();
|
||||
const isMobileView = getIsMobileView(state);
|
||||
const showTaskList = isUserFirstAdmin && taskListStatus && !isMobileView;
|
||||
const subscriptionProduct = getSubscriptionProduct(state);
|
||||
|
||||
|
@ -107,6 +107,11 @@ const initialState = {
|
||||
config: {PostEditTimeLimit: -1},
|
||||
},
|
||||
},
|
||||
views: {
|
||||
browser: {
|
||||
windowSize: '',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('channel_info_rhs/about_area_gm', () => {
|
||||
|
@ -160,14 +160,14 @@ export default class LinkingLandingPage extends PureComponent<Props, State> {
|
||||
renderGoNativeAppMessage = () => {
|
||||
return (
|
||||
<a
|
||||
href={Utils.isMobile() ? '#' : this.state.nativeLocation}
|
||||
href={UserAgent.isMobile() ? '#' : this.state.nativeLocation}
|
||||
onMouseDown={() => {
|
||||
this.setPreference(LandingPreferenceTypes.MATTERMOSTAPP, true);
|
||||
}}
|
||||
onClick={() => {
|
||||
this.setPreference(LandingPreferenceTypes.MATTERMOSTAPP, true);
|
||||
this.setState({redirectPage: true, navigating: true});
|
||||
if (Utils.isMobile()) {
|
||||
if (UserAgent.isMobile()) {
|
||||
if (UserAgent.isAndroidWeb()) {
|
||||
const timeout = setTimeout(() => {
|
||||
window.location.replace(this.getDownloadLink()!);
|
||||
|
@ -22,14 +22,6 @@ const suggestionProviders = [
|
||||
new SearchUserProvider(jest.fn()),
|
||||
];
|
||||
|
||||
jest.mock('utils/utils', () => {
|
||||
const original = jest.requireActual('utils/utils');
|
||||
return {
|
||||
...original,
|
||||
isMobile: jest.fn(() => false),
|
||||
};
|
||||
});
|
||||
|
||||
const wrapIntl = (component: JSX.Element) => (
|
||||
<IntlProvider
|
||||
locale={'en'}
|
||||
|
@ -8,6 +8,7 @@ import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {openMenu as openRhsMenu} from 'actions/views/rhs';
|
||||
import {getIsRhsMenuOpen} from 'selectors/rhs';
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import {GlobalState} from 'types/store';
|
||||
|
||||
@ -23,6 +24,7 @@ function mapStateToProps(state: GlobalState) {
|
||||
|
||||
return {
|
||||
teamDisplayName: currentTeam && currentTeam.display_name,
|
||||
isMobileView: getIsMobileView(state),
|
||||
isOpen: getIsRhsMenuOpen(state),
|
||||
siteName,
|
||||
};
|
||||
|
@ -8,7 +8,6 @@ import {CSSTransition} from 'react-transition-group';
|
||||
|
||||
import * as GlobalActions from 'actions/global_actions';
|
||||
import {Constants} from 'utils/constants';
|
||||
import * as Utils from 'utils/utils';
|
||||
|
||||
import MainMenu from 'components/main_menu';
|
||||
|
||||
@ -17,6 +16,7 @@ type Action = {
|
||||
}
|
||||
|
||||
type Props = {
|
||||
isMobileView: boolean;
|
||||
isOpen: boolean;
|
||||
teamDisplayName?: string;
|
||||
siteName?: string;
|
||||
@ -42,7 +42,7 @@ export default class SidebarRightMenu extends React.PureComponent<Props> {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('sidebar--menu', {'move--left': this.props.isOpen && Utils.isMobile()})}
|
||||
className={classNames('sidebar--menu', {'move--left': this.props.isOpen && this.props.isMobileView})}
|
||||
id='sidebar-menu'
|
||||
>
|
||||
<div className='team__header theme'>
|
||||
@ -56,7 +56,7 @@ export default class SidebarRightMenu extends React.PureComponent<Props> {
|
||||
|
||||
<div className='nav-pills__container mobile-main-menu'>
|
||||
<CSSTransition
|
||||
in={this.props.isOpen && Utils.isMobile()}
|
||||
in={this.props.isOpen && this.props.isMobileView}
|
||||
classNames='MobileRightSidebarMenu'
|
||||
enter={true}
|
||||
exit={true}
|
||||
|
@ -10,6 +10,8 @@ import {Permissions} from 'mattermost-redux/constants';
|
||||
import {haveITeamPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
import {ActionResult, GenericAction} from 'mattermost-redux/types/actions';
|
||||
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import {GlobalState} from 'types/store/index';
|
||||
|
||||
import {Team} from '@mattermost/types/teams';
|
||||
@ -33,6 +35,7 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
|
||||
return {
|
||||
maxFileSize,
|
||||
canInviteTeamMembers,
|
||||
isMobileView: getIsMobileView(state),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ describe('components/TeamSettings', () => {
|
||||
collapseModal: jest.fn(),
|
||||
actions: baseActions,
|
||||
canInviteTeamMembers: true,
|
||||
isMobileView: false,
|
||||
};
|
||||
|
||||
test('should handle bad updateTeamIcon function call', () => {
|
||||
|
@ -5,7 +5,7 @@ import React, {ChangeEvent, MouseEvent, ReactNode} from 'react';
|
||||
import {FormattedMessage, FormattedDate} from 'react-intl';
|
||||
|
||||
import Constants from 'utils/constants';
|
||||
import {imageURLForTeam, isMobile, localizeMessage, moveCursorToEnd} from 'utils/utils';
|
||||
import {imageURLForTeam, localizeMessage, moveCursorToEnd} from 'utils/utils';
|
||||
import {t} from 'utils/i18n';
|
||||
|
||||
import SettingItemMax from 'components/setting_item_max';
|
||||
@ -390,7 +390,7 @@ export default class GeneralTab extends React.PureComponent<Props, State> {
|
||||
if (this.props.activeSection === 'name') {
|
||||
const inputs = [];
|
||||
|
||||
const teamNameLabel = isMobile() ? '' : (
|
||||
const teamNameLabel = this.props.isMobileView ? '' : (
|
||||
<FormattedMessage
|
||||
id='general_tab.teamName'
|
||||
defaultMessage='Team Name'
|
||||
@ -449,7 +449,7 @@ export default class GeneralTab extends React.PureComponent<Props, State> {
|
||||
if (this.props.activeSection === 'description') {
|
||||
const inputs = [];
|
||||
|
||||
const teamDescriptionLabel = isMobile() ? '' : (
|
||||
const teamDescriptionLabel = this.props.isMobileView ? '' : (
|
||||
<FormattedMessage
|
||||
id='general_tab.teamDescription'
|
||||
defaultMessage='Team Description'
|
||||
@ -557,7 +557,7 @@ export default class GeneralTab extends React.PureComponent<Props, State> {
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
minMessage = isMobile() ? localizeMessage('general_tab.teamIconEditHintMobile', 'Click to upload an image') : localizeMessage('general_tab.teamIconEditHint', 'Click \'Edit\' to upload an image.');
|
||||
minMessage = this.props.isMobileView ? localizeMessage('general_tab.teamIconEditHintMobile', 'Click to upload an image') : localizeMessage('general_tab.teamIconEditHint', 'Click \'Edit\' to upload an image.');
|
||||
}
|
||||
|
||||
teamIconSection = (
|
||||
|
@ -13,9 +13,10 @@ import {Post} from '@mattermost/types/posts';
|
||||
|
||||
import {FakePost} from 'types/store/rhs';
|
||||
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
import {makePrepareReplyIdsForThreadViewer, makeGetThreadLastViewedAt} from 'selectors/views/threads';
|
||||
|
||||
import {GlobalState} from 'types/store';
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
import ThreadViewerVirtualized from './virtualized_thread_viewer';
|
||||
|
||||
@ -51,6 +52,7 @@ function makeMapStateToProps() {
|
||||
return {
|
||||
currentUserId,
|
||||
directTeammate,
|
||||
isMobileView: getIsMobileView(state),
|
||||
lastPost,
|
||||
replyListIds,
|
||||
lastViewedAt,
|
||||
|
@ -54,7 +54,6 @@ describe('components/threading/VirtualizedThreadViewer', () => {
|
||||
socketConnectionStatus: true,
|
||||
actions,
|
||||
directTeammate,
|
||||
isCollapsedThreadsEnabled: false,
|
||||
posts: [post],
|
||||
lastPost: post,
|
||||
onCardClick: () => {},
|
||||
@ -62,6 +61,7 @@ describe('components/threading/VirtualizedThreadViewer', () => {
|
||||
replyListIds: [],
|
||||
teamId: '',
|
||||
useRelativeTimestamp: true,
|
||||
isMobileView: false,
|
||||
isThreadView: true,
|
||||
lastViewedAt: 0,
|
||||
newMessagesSeparatorActions: [],
|
||||
|
@ -36,6 +36,7 @@ type Props = {
|
||||
replyListIds: string[];
|
||||
selected: Post | FakePost;
|
||||
useRelativeTimestamp: boolean;
|
||||
isMobileView: boolean;
|
||||
isThreadView: boolean;
|
||||
lastViewedAt: number;
|
||||
newMessagesSeparatorActions: PluginComponent[];
|
||||
@ -43,7 +44,6 @@ type Props = {
|
||||
|
||||
type State = {
|
||||
createCommentHeight: number;
|
||||
isMobile: boolean;
|
||||
isScrolling: boolean;
|
||||
topRhsPostId?: string;
|
||||
userScrolled: boolean;
|
||||
@ -96,7 +96,6 @@ class ThreadViewerVirtualized extends PureComponent<Props, State> {
|
||||
super(props);
|
||||
|
||||
const postIndex = this.getInitialPostIndex();
|
||||
const isMobile = Utils.isMobile();
|
||||
|
||||
this.initRangeToRender = [
|
||||
Math.max(postIndex - 30, 0),
|
||||
@ -110,7 +109,6 @@ class ThreadViewerVirtualized extends PureComponent<Props, State> {
|
||||
|
||||
this.state = {
|
||||
createCommentHeight: 0,
|
||||
isMobile,
|
||||
isScrolling: false,
|
||||
userScrolled: false,
|
||||
userScrolledToBottom: false,
|
||||
@ -125,12 +123,10 @@ class ThreadViewerVirtualized extends PureComponent<Props, State> {
|
||||
|
||||
componentDidMount() {
|
||||
this.mounted = true;
|
||||
window.addEventListener('resize', this.handleWindowResize);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
window.removeEventListener('resize', this.handleWindowResize);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
@ -156,15 +152,6 @@ class ThreadViewerVirtualized extends PureComponent<Props, State> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
handleWindowResize = () => {
|
||||
const isMobile = Utils.isMobile();
|
||||
if (isMobile !== this.state.isMobile) {
|
||||
this.setState({
|
||||
isMobile,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
initScrollToIndex = (): {index: number; position: string; offset?: number} => {
|
||||
const {highlightedPostId, replyListIds} = this.props;
|
||||
|
||||
@ -207,7 +194,7 @@ class ThreadViewerVirtualized extends PureComponent<Props, State> {
|
||||
updatedState.userScrolled = true;
|
||||
updatedState.userScrolledToBottom = userScrolledToBottom;
|
||||
|
||||
if (this.state.isMobile) {
|
||||
if (this.props.isMobileView) {
|
||||
if (!this.state.isScrolling) {
|
||||
updatedState.isScrolling = true;
|
||||
}
|
||||
@ -241,7 +228,7 @@ class ThreadViewerVirtualized extends PureComponent<Props, State> {
|
||||
overscanStartIndex,
|
||||
overscanStopIndex,
|
||||
}: OnItemsRenderedArgs) => {
|
||||
if (this.state.isMobile) {
|
||||
if (this.props.isMobileView) {
|
||||
this.updateFloatingTimestamp(visibleStartIndex);
|
||||
}
|
||||
this.setState({
|
||||
@ -434,11 +421,11 @@ class ThreadViewerVirtualized extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const {isMobile, topRhsPostId} = this.state;
|
||||
const {topRhsPostId} = this.state;
|
||||
|
||||
return (
|
||||
<>
|
||||
{isMobile && topRhsPostId && !this.props.useRelativeTimestamp && (
|
||||
{this.props.isMobileView && topRhsPostId && !this.props.useRelativeTimestamp && (
|
||||
<FloatingTimestamp
|
||||
isRhsPost={true}
|
||||
isScrolling={this.state.isScrolling}
|
||||
|
@ -6,7 +6,8 @@ import {connect} from 'react-redux';
|
||||
import {getUser, makeGetDisplayName} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {GlobalState} from '@mattermost/types/store';
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
import {GlobalState} from 'types/store';
|
||||
|
||||
import UserProfile from './user_profile';
|
||||
|
||||
@ -25,6 +26,7 @@ function makeMapStateToProps() {
|
||||
displayName: getDisplayName(state, ownProps.userId, true),
|
||||
user,
|
||||
theme,
|
||||
isMobileView: getIsMobileView(state),
|
||||
isShared: Boolean(user && user.remote_id),
|
||||
};
|
||||
};
|
||||
|
@ -13,6 +13,7 @@ describe('components/UserProfile', () => {
|
||||
const baseProps = {
|
||||
displayName: 'nickname',
|
||||
isBusy: false,
|
||||
isMobileView: false,
|
||||
user: {username: 'username'} as UserProfileType,
|
||||
userId: 'user_id',
|
||||
theme: Preferences.THEMES.onyx,
|
||||
|
@ -12,7 +12,7 @@ import {UserProfile as UserProfileType} from '@mattermost/types/users';
|
||||
import {Theme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {isGuest} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
import {imageURLForUser, isMobile} from 'utils/utils';
|
||||
import {imageURLForUser} from 'utils/utils';
|
||||
|
||||
import OverlayTrigger, {BaseOverlayTrigger} from 'components/overlay_trigger';
|
||||
import ProfilePopover from 'components/profile_popover';
|
||||
@ -34,6 +34,7 @@ export type UserProfileProps = {
|
||||
colorize?: boolean;
|
||||
hasMention?: boolean;
|
||||
hideStatus?: boolean;
|
||||
isMobileView: boolean;
|
||||
isRHS?: boolean;
|
||||
channelId?: string;
|
||||
theme?: Theme;
|
||||
@ -68,6 +69,7 @@ export default class UserProfile extends PureComponent<UserProfileProps> {
|
||||
displayName,
|
||||
displayUsername,
|
||||
isBusy,
|
||||
isMobileView,
|
||||
isRHS,
|
||||
isShared,
|
||||
hasMention,
|
||||
@ -110,7 +112,7 @@ export default class UserProfile extends PureComponent<UserProfileProps> {
|
||||
}
|
||||
|
||||
let placement = 'right';
|
||||
if (isRHS && !isMobile()) {
|
||||
if (isRHS && !isMobileView) {
|
||||
placement = 'left';
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,12 @@ import {
|
||||
import {clearErrors, logError} from 'mattermost-redux/actions/errors';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
|
||||
import {GlobalState} from '@mattermost/types/store';
|
||||
import {ActionFunc} from 'mattermost-redux/types/actions';
|
||||
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
import UserSettingsGeneralTab, {Props} from './user_settings_general';
|
||||
|
||||
function mapStateToProps(state: GlobalState) {
|
||||
@ -34,6 +37,7 @@ function mapStateToProps(state: GlobalState) {
|
||||
const ldapPictureAttributeSet = config.LdapPictureAttributeSet === 'true';
|
||||
|
||||
return {
|
||||
isMobileView: getIsMobileView(state),
|
||||
requireEmailVerification,
|
||||
maxFileSize,
|
||||
ldapFirstNameAttributeSet,
|
||||
|
@ -34,6 +34,7 @@ describe('components/user_settings/general/UserSettingsGeneral', () => {
|
||||
activeSection: '',
|
||||
closeModal: jest.fn(),
|
||||
collapseModal: jest.fn(),
|
||||
isMobileView: false,
|
||||
actions: {
|
||||
logError: jest.fn(),
|
||||
clearErrors: jest.fn(),
|
||||
|
@ -101,6 +101,7 @@ export type Props = {
|
||||
activeSection?: string;
|
||||
closeModal: () => void;
|
||||
collapseModal: () => void;
|
||||
isMobileView: boolean;
|
||||
maxFileSize: number;
|
||||
actions: {
|
||||
logError: ({message, type}: {message: any; type: string}, status: boolean) => void;
|
||||
@ -934,7 +935,7 @@ export class UserSettingsGeneralTab extends React.Component<Props, State> {
|
||||
defaultMessage="Click 'Edit' to add your full name"
|
||||
/>
|
||||
);
|
||||
if (Utils.isMobile()) {
|
||||
if (this.props.isMobileView) {
|
||||
describe = (
|
||||
<FormattedMessage
|
||||
id='user.settings.general.mobile.emptyName'
|
||||
@ -984,7 +985,7 @@ export class UserSettingsGeneralTab extends React.Component<Props, State> {
|
||||
defaultMessage='Nickname'
|
||||
/>
|
||||
);
|
||||
if (Utils.isMobile()) {
|
||||
if (this.props.isMobileView) {
|
||||
nicknameLabel = '';
|
||||
}
|
||||
|
||||
@ -1046,7 +1047,7 @@ export class UserSettingsGeneralTab extends React.Component<Props, State> {
|
||||
defaultMessage="Click 'Edit' to add a nickname"
|
||||
/>
|
||||
);
|
||||
if (Utils.isMobile()) {
|
||||
if (this.props.isMobileView) {
|
||||
describe = (
|
||||
<FormattedMessage
|
||||
id='user.settings.general.mobile.emptyNickname'
|
||||
@ -1086,7 +1087,7 @@ export class UserSettingsGeneralTab extends React.Component<Props, State> {
|
||||
defaultMessage='Username'
|
||||
/>
|
||||
);
|
||||
if (Utils.isMobile()) {
|
||||
if (this.props.isMobileView) {
|
||||
usernameLabel = '';
|
||||
}
|
||||
|
||||
@ -1187,7 +1188,7 @@ export class UserSettingsGeneralTab extends React.Component<Props, State> {
|
||||
defaultMessage='Position'
|
||||
/>
|
||||
);
|
||||
if (Utils.isMobile()) {
|
||||
if (this.props.isMobileView) {
|
||||
positionLabel = '';
|
||||
}
|
||||
|
||||
@ -1250,7 +1251,7 @@ export class UserSettingsGeneralTab extends React.Component<Props, State> {
|
||||
defaultMessage="Click 'Edit' to add your job title / position"
|
||||
/>
|
||||
);
|
||||
if (Utils.isMobile()) {
|
||||
if (this.props.isMobileView) {
|
||||
describe = (
|
||||
<FormattedMessage
|
||||
id='user.settings.general.mobile.emptyPosition'
|
||||
@ -1332,7 +1333,7 @@ export class UserSettingsGeneralTab extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
let minMessage: JSX.Element|string = formatMessage(holders.uploadImage);
|
||||
if (Utils.isMobile()) {
|
||||
if (this.props.isMobileView) {
|
||||
minMessage = formatMessage(holders.uploadImageMobile);
|
||||
}
|
||||
if (user.last_picture_update > 0) {
|
||||
|
@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import store from 'stores/redux_store';
|
||||
|
||||
/**
|
||||
* @deprecated This is a horrible hack that shouldn't used done elsewhere because we shouldn't be accessing the global
|
||||
* store directly, but it's too hard to get this value into these component properly without rewriting everything.
|
||||
* These components will eventually be replaced by the newer components in `components/menu` anyway.
|
||||
*/
|
||||
export function isMobile() {
|
||||
return getIsMobileView(store.getState());
|
||||
}
|
@ -171,3 +171,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Menu__content {
|
||||
&.openLeft {
|
||||
right: 0;
|
||||
left: inherit;
|
||||
}
|
||||
|
||||
&.openUp {
|
||||
@media screen and (min-width: 768px) {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,15 @@ import {shallow} from 'enzyme';
|
||||
|
||||
import Menu from './menu';
|
||||
|
||||
jest.mock('./is_mobile_view_hack', () => ({
|
||||
isMobile: jest.fn(() => false),
|
||||
}));
|
||||
|
||||
(global as any).MutationObserver = class {
|
||||
public disconnect() {}
|
||||
public observe() {}
|
||||
};
|
||||
|
||||
jest.mock('utils/utils', () => {
|
||||
const original = jest.requireActual('utils/utils');
|
||||
return {
|
||||
...original,
|
||||
isMobile: jest.fn(() => false),
|
||||
};
|
||||
});
|
||||
|
||||
describe('components/Menu', () => {
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = shallow(<Menu ariaLabel='test-label'>{'text'}</Menu>);
|
||||
@ -68,46 +64,7 @@ describe('components/Menu', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test('should match snapshot with openLeft and openUp when is mobile', () => {
|
||||
const utils = require('utils/utils'); //eslint-disable-line global-require
|
||||
utils.isMobile.mockReturnValue(true);
|
||||
|
||||
const wrapper = shallow(
|
||||
<Menu
|
||||
openLeft={true}
|
||||
openUp={true}
|
||||
ariaLabel='test-label'
|
||||
>
|
||||
{'text'}
|
||||
</Menu>,
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchInlineSnapshot(`
|
||||
<div
|
||||
aria-label="test-label"
|
||||
className="a11y__popup Menu"
|
||||
role="menu"
|
||||
>
|
||||
<ul
|
||||
className="Menu__content dropdown-menu"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"left": "inherit",
|
||||
"right": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
text
|
||||
</ul>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
test('should match snapshot with openLeft and openUp', () => {
|
||||
const utils = require('utils/utils'); //eslint-disable-line global-require
|
||||
utils.isMobile.mockReturnValue(false);
|
||||
|
||||
const wrapper = shallow(
|
||||
<Menu
|
||||
openLeft={true}
|
||||
@ -125,16 +82,9 @@ describe('components/Menu', () => {
|
||||
role="menu"
|
||||
>
|
||||
<ul
|
||||
className="Menu__content dropdown-menu"
|
||||
className="Menu__content dropdown-menu openLeft openUp"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"bottom": "100%",
|
||||
"left": "inherit",
|
||||
"right": 0,
|
||||
"top": "auto",
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
>
|
||||
text
|
||||
</ul>
|
||||
@ -143,8 +93,6 @@ describe('components/Menu', () => {
|
||||
});
|
||||
|
||||
test('should hide the correct dividers', () => {
|
||||
const utils = require('utils/utils'); //eslint-disable-line global-require
|
||||
utils.isMobile.mockReturnValue(false);
|
||||
const pseudoMenu = document.createElement('div');
|
||||
const listOfItems = [
|
||||
'menu-divider',
|
||||
@ -255,8 +203,6 @@ describe('components/Menu', () => {
|
||||
});
|
||||
|
||||
test('should hide the correct dividers on mobile', () => {
|
||||
const utils = require('utils/utils'); //eslint-disable-line global-require
|
||||
utils.isMobile.mockReturnValue(false);
|
||||
const pseudoMenu = document.createElement('div');
|
||||
const listOfItems = [
|
||||
'mobile-menu-divider',
|
||||
|
@ -4,8 +4,6 @@
|
||||
import React, {CSSProperties} from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import {isMobile} from 'utils/utils';
|
||||
|
||||
import SubMenuItem from './menu_items/submenu_item';
|
||||
|
||||
import MenuHeader from './menu_header';
|
||||
@ -123,15 +121,6 @@ export default class Menu extends React.PureComponent<Props> {
|
||||
let styles: CSSProperties = {};
|
||||
if (customStyles) {
|
||||
styles = customStyles;
|
||||
} else {
|
||||
if (openLeft) {
|
||||
styles.left = 'inherit';
|
||||
styles.right = 0;
|
||||
}
|
||||
if (openUp && !isMobile()) {
|
||||
styles.bottom = '100%';
|
||||
styles.top = 'auto';
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@ -145,7 +134,14 @@ export default class Menu extends React.PureComponent<Props> {
|
||||
id={listId}
|
||||
ref={this.node}
|
||||
style={styles}
|
||||
className={classNames('Menu__content dropdown-menu', this.props.className)}
|
||||
className={classNames(
|
||||
'Menu__content dropdown-menu',
|
||||
{
|
||||
openLeft,
|
||||
openUp,
|
||||
},
|
||||
this.props.className,
|
||||
)}
|
||||
onClick={this.handleMenuClick}
|
||||
>
|
||||
{children}
|
||||
|
@ -8,6 +8,10 @@ import Constants from 'utils/constants';
|
||||
|
||||
import SubMenuItem from './submenu_item';
|
||||
|
||||
jest.mock('../is_mobile_view_hack', () => ({
|
||||
isMobile: jest.fn(() => false),
|
||||
}));
|
||||
|
||||
describe('components/widgets/menu/menu_items/submenu_item', () => {
|
||||
test('empty subMenu should match snapshot', () => {
|
||||
const wrapper = mount(
|
||||
|
@ -6,10 +6,13 @@ import classNames from 'classnames';
|
||||
|
||||
import * as Keyboard from 'utils/keyboard';
|
||||
import * as Utils from 'utils/utils';
|
||||
|
||||
import {showMobileSubMenuModal} from 'actions/global_actions';
|
||||
|
||||
import type {Menu} from 'types/store/plugins';
|
||||
|
||||
import {isMobile as isMobileViewHack} from '../is_mobile_view_hack';
|
||||
|
||||
import './menu_item.scss';
|
||||
import Constants from 'utils/constants';
|
||||
|
||||
@ -94,7 +97,7 @@ export default class SubMenuItem extends React.PureComponent<Props, State> {
|
||||
private onClick = (event: React.SyntheticEvent<HTMLElement>) => {
|
||||
event.preventDefault();
|
||||
const {id, postId, subMenu, action, root, isHeader} = this.props;
|
||||
const isMobile = Utils.isMobile();
|
||||
const isMobile = isMobileViewHack();
|
||||
if (isHeader) {
|
||||
event.stopPropagation();
|
||||
return;
|
||||
@ -141,7 +144,7 @@ export default class SubMenuItem extends React.PureComponent<Props, State> {
|
||||
|
||||
public render() {
|
||||
const {id, postId, text, selectedValueText, subMenu, icon, filter, ariaLabel, direction, styleSelectableItem, extraText, renderSelected, rightDecorator, tabIndex} = this.props;
|
||||
const isMobile = Utils.isMobile();
|
||||
const isMobile = isMobileViewHack();
|
||||
|
||||
if (filter && !filter(id)) {
|
||||
return ('');
|
||||
|
@ -5,7 +5,11 @@ import React from 'react';
|
||||
import {shallow, mount} from 'enzyme';
|
||||
import {Modal} from 'react-bootstrap';
|
||||
|
||||
import SubMenuModal from 'components/widgets/menu/menu_modals/submenu_modal/submenu_modal';
|
||||
import SubMenuModal from './submenu_modal';
|
||||
|
||||
jest.mock('../../is_mobile_view_hack', () => ({
|
||||
isMobile: jest.fn(() => false),
|
||||
}));
|
||||
|
||||
(global as any).MutationObserver = class {
|
||||
public disconnect() {}
|
||||
|
@ -4,7 +4,7 @@
|
||||
import React from 'react';
|
||||
import {CSSTransition} from 'react-transition-group';
|
||||
|
||||
import {isMobile} from 'utils/utils';
|
||||
import {isMobile} from './is_mobile_view_hack';
|
||||
|
||||
const ANIMATION_DURATION = 80;
|
||||
|
||||
|
@ -35,6 +35,11 @@ describe('selectors/onboarding', () => {
|
||||
profiles,
|
||||
},
|
||||
},
|
||||
views: {
|
||||
browser: {
|
||||
windowSize: '',
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
const [showTaskList, firstTimeOnboarding] = getShowTaskListBool(state);
|
||||
@ -65,6 +70,11 @@ describe('selectors/onboarding', () => {
|
||||
profiles,
|
||||
},
|
||||
},
|
||||
views: {
|
||||
browser: {
|
||||
windowSize: '',
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
const [showTaskList, firstTimeOnboarding] = getShowTaskListBool(state);
|
||||
@ -95,6 +105,11 @@ describe('selectors/onboarding', () => {
|
||||
profiles,
|
||||
},
|
||||
},
|
||||
views: {
|
||||
browser: {
|
||||
windowSize: '',
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
const [showTaskList, firstTimeOnboarding] = getShowTaskListBool(state);
|
||||
@ -128,6 +143,11 @@ describe('selectors/onboarding', () => {
|
||||
profiles,
|
||||
},
|
||||
},
|
||||
views: {
|
||||
browser: {
|
||||
windowSize: '',
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
const [showTaskList, firstTimeOnboarding] = getShowTaskListBool(state);
|
||||
@ -165,6 +185,11 @@ describe('selectors/onboarding', () => {
|
||||
profiles,
|
||||
},
|
||||
},
|
||||
views: {
|
||||
browser: {
|
||||
windowSize: '',
|
||||
},
|
||||
},
|
||||
} as unknown as GlobalState;
|
||||
|
||||
const [showTaskList, firstTimeOnboarding] = getShowTaskListBool(state);
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {isMobile} from 'utils/utils';
|
||||
|
||||
import {createSelector} from 'mattermost-redux/selectors/create_selector';
|
||||
import {makeGetCategory, getBool} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentUser, isFirstAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {OnboardingTaskCategory, OnboardingTaskList} from 'components/onboarding_tasks';
|
||||
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import {GlobalState} from 'types/store';
|
||||
|
||||
import {RecommendedNextStepsLegacy, Preferences} from 'utils/constants';
|
||||
@ -125,9 +125,8 @@ export const getShowTaskListBool = createSelector(
|
||||
(state: GlobalState) => state,
|
||||
(state: GlobalState) => getCategory(state, OnboardingTaskCategory),
|
||||
(state: GlobalState) => getCategory(state, Preferences.RECOMMENDED_NEXT_STEPS),
|
||||
(state, onboardingPreferences, legacyStepsPreferences) => {
|
||||
const isMobileView = isMobile();
|
||||
|
||||
getIsMobileView,
|
||||
(state, onboardingPreferences, legacyStepsPreferences, isMobileView) => {
|
||||
// conditions to validate scenario where users (initially first_admins) had already set any of the onboarding task list preferences values.
|
||||
// We check wether the preference value exists meaning the onboarding tasks list already started no matter what the state of the process is
|
||||
const hasUserStartedOnboardingTaskListProcess = onboardingPreferences?.some((pref) =>
|
||||
|
@ -47,12 +47,10 @@ import {searchForTerm} from 'actions/post_actions';
|
||||
import {getHistory} from 'utils/browser_history';
|
||||
import * as Keyboard from 'utils/keyboard';
|
||||
import * as UserAgent from 'utils/user_agent';
|
||||
import {isDesktopApp} from 'utils/user_agent';
|
||||
import {t} from 'utils/i18n';
|
||||
import store from 'stores/redux_store.jsx';
|
||||
|
||||
import {getCurrentLocale, getTranslations} from 'selectors/i18n';
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
|
||||
import {FileInfo} from '@mattermost/types/files';
|
||||
import {Team} from '@mattermost/types/teams';
|
||||
@ -890,10 +888,6 @@ export function isValidBotUsername(name: string) {
|
||||
return error;
|
||||
}
|
||||
|
||||
export function isMobile() {
|
||||
return getIsMobileView(store.getState());
|
||||
}
|
||||
|
||||
export function loadImage(
|
||||
url: string,
|
||||
onLoad: ((this: XMLHttpRequest, ev: ProgressEvent) => any) | null,
|
||||
@ -1720,9 +1714,9 @@ const TrackFlowSources: Record<string, string> = {
|
||||
};
|
||||
|
||||
function getTrackFlowSource() {
|
||||
if (isMobile()) {
|
||||
if (UserAgent.isMobile()) {
|
||||
return TrackFlowSources.wm;
|
||||
} else if (isDesktopApp()) {
|
||||
} else if (UserAgent.isDesktopApp()) {
|
||||
return TrackFlowSources.d;
|
||||
}
|
||||
return TrackFlowSources.wd;
|
||||
|
Loading…
Reference in New Issue
Block a user