From e443a692656ad10bcb144f9ffe8bf1ab6954ea2a Mon Sep 17 00:00:00 2001 From: Avinash Lingaloo Date: Thu, 4 Aug 2022 12:26:27 +0400 Subject: [PATCH] MM-45344 Gekidou Remove (#6522) * added MENU_ITEM_HEIGHT to constant/view * fix user presence and your profile * added MENU_ITEM_HEIGHT to constant/view * fix user presence and your profile * UI Polish - Custom Status * UI Polish - Settings * UI Polish - logout * refactored styles * removed 'throws DataOperatorException' from './database/` * fix for copy link option * fix autoresponder 1. user should be allowed to enter paragraph 2. the OOO was not immediately being updated on the notification main screen. The fix is to cal fetchStatusInBatch after the updateMe operation * About Screen - code clean up * removed MenuItem component from common_post_options * removed MenuItem from Settings * refactored show_more and recent_item * removed menu_item component * Update setting_container.tsx * PR review correction * Update setting_container.tsx * Update recent_item.tsx --- .../common_post_options/base_option/index.tsx | 54 ++-- .../__snapshots__/index.test.tsx.snap | 235 ------------------ app/components/menu_item/index.test.tsx | 42 ---- app/components/menu_item/index.tsx | 173 ------------- app/components/option_item/index.tsx | 7 +- app/components/status_label/index.tsx | 7 +- .../operator/base_data_operator/index.ts | 6 +- .../server_data_operator/handlers/group.ts | 3 - app/screens/about/server_version.tsx | 57 ----- .../options/custom_status/custom_label.tsx | 19 +- .../custom_status/custom_status_emoji.tsx | 5 +- .../custom_status/custom_status_text.tsx | 11 +- .../options/custom_status/index.tsx | 45 ++-- .../home/account/components/options/index.tsx | 61 ++--- .../components/options/logout/index.tsx | 73 ++---- .../components/options/settings/index.tsx | 34 +-- .../options/user_presence/index.tsx | 67 +++-- .../components/options/your_profile/index.tsx | 24 +- .../search/initial/modifiers/show_more.tsx | 22 +- app/screens/post_options/post_options.tsx | 2 +- app/screens/settings/about/tos_privacy.tsx | 44 ++-- app/screens/settings/config.ts | 36 +-- app/screens/settings/display/display.tsx | 27 +- .../notification_auto_responder.tsx | 8 +- .../settings/notifications/notifications.tsx | 19 +- app/screens/settings/setting_item.tsx | 47 ++-- app/screens/settings/setting_row_label.tsx | 44 ---- app/screens/settings/settings.tsx | 8 +- app/screens/snack_bar/index.tsx | 4 +- app/screens/thread_options/thread_options.tsx | 2 +- 30 files changed, 284 insertions(+), 902 deletions(-) delete mode 100644 app/components/menu_item/__snapshots__/index.test.tsx.snap delete mode 100644 app/components/menu_item/index.test.tsx delete mode 100644 app/components/menu_item/index.tsx delete mode 100644 app/screens/about/server_version.tsx delete mode 100644 app/screens/settings/setting_row_label.tsx diff --git a/app/components/common_post_options/base_option/index.tsx b/app/components/common_post_options/base_option/index.tsx index c5d06f4266..df85900dba 100644 --- a/app/components/common_post_options/base_option/index.tsx +++ b/app/components/common_post_options/base_option/index.tsx @@ -1,64 +1,38 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useMemo} from 'react'; +import React from 'react'; +import {useIntl} from 'react-intl'; -import FormattedText from '@components/formatted_text'; -import MenuItem from '@components/menu_item'; -import {useTheme} from '@context/theme'; -import {makeStyleSheetFromTheme} from '@utils/theme'; -import {typography} from '@utils/typography'; - -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - destructive: { - color: theme.dndIndicator, - }, - label: { - color: theme.centerChannelColor, - ...typography('Body', 200), - }, - iconContainerStyle: { - marginLeft: 0, - }, -})); +import OptionItem from '@components/option_item'; type BaseOptionType = { - i18nId: string; defaultMessage: string; + i18nId: string; iconName: string; + isDestructive?: boolean; onPress: () => void; testID: string; - isDestructive?: boolean; } const BaseOption = ({ - i18nId, defaultMessage, + i18nId, iconName, + isDestructive = false, onPress, testID, - isDestructive = false, }: BaseOptionType) => { - const theme = useTheme(); - const styles = getStyleSheet(theme); - - const label = useMemo(() => ( - - ), [i18nId, defaultMessage, theme]); + const intl = useIntl(); return ( - ); }; diff --git a/app/components/menu_item/__snapshots__/index.test.tsx.snap b/app/components/menu_item/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 6fde1aafa6..0000000000 --- a/app/components/menu_item/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,235 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DrawerItem should match snapshot 1`] = ` - - - - - - - - - - default message - - - - - - - -`; - -exports[`DrawerItem should match snapshot without separator and centered false 1`] = ` - - - - - - - - - - default message - - - - - - -`; diff --git a/app/components/menu_item/index.test.tsx b/app/components/menu_item/index.test.tsx deleted file mode 100644 index 7795dd1a18..0000000000 --- a/app/components/menu_item/index.test.tsx +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; - -import {Preferences} from '@constants'; -import {renderWithIntl} from '@test/intl-test-helper'; - -import MenuItem from '.'; - -describe('DrawerItem', () => { - const baseProps = { - onPress: () => null, - testID: 'test-id', - centered: true, - defaultMessage: 'default message', - i18nId: 'i18-id', - iconName: 'icon-name', - isDestructor: true, - separator: true, - theme: Preferences.THEMES.denim, - }; - - test('should match snapshot', () => { - const wrapper = renderWithIntl(); - - expect(wrapper.toJSON()).toMatchSnapshot(); - }); - - test('should match snapshot without separator and centered false', () => { - const props = { - ...baseProps, - centered: false, - separator: false, - }; - const wrapper = renderWithIntl( - , - ); - - expect(wrapper.toJSON()).toMatchSnapshot(); - }); -}); diff --git a/app/components/menu_item/index.tsx b/app/components/menu_item/index.tsx deleted file mode 100644 index 345ba9ba7a..0000000000 --- a/app/components/menu_item/index.tsx +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {ReactNode} from 'react'; -import {Platform, StyleProp, TextStyle, View, ViewStyle} from 'react-native'; - -import CompassIcon from '@components/compass_icon'; -import FormattedText from '@components/formatted_text'; -import TouchableWithFeedback from '@components/touchable_with_feedback'; -import {useTheme} from '@context/theme'; -import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; - -export const ITEM_HEIGHT = 50; -const getStyleSheet = makeStyleSheetFromTheme((theme) => { - return { - container: { - flexDirection: 'row', - minHeight: ITEM_HEIGHT, - }, - iconContainer: { - width: 45, - height: ITEM_HEIGHT, - alignItems: 'center', - justifyContent: 'center', - marginLeft: 5, - }, - icon: { - color: changeOpacity(theme.centerChannelColor, 0.64), - fontSize: 24, - }, - labelContainer: { - flex: 1, - justifyContent: 'center', - paddingVertical: 14, - }, - centerLabel: { - textAlign: 'center', - textAlignVertical: 'center', - }, - label: { - color: changeOpacity(theme.centerChannelColor, 0.5), - fontSize: 17, - textAlignVertical: 'center', - includeFontPadding: false, - }, - divider: { - backgroundColor: changeOpacity(theme.centerChannelColor, 0.12), - height: 1, - }, - chevron: { - alignSelf: 'center', - color: changeOpacity(theme.centerChannelColor, 0.64), - fontSize: 24, - marginRight: 8, - }, - linkContainer: { - marginHorizontal: 15, - color: theme.linkColor, - }, - mainContainer: { - flexDirection: 'column', - }, - }; -}); - -export type MenuItemProps = { - centered?: boolean; - chevronStyle?: StyleProp; - containerStyle?: StyleProp; - defaultMessage?: string; - i18nId?: string; - iconContainerStyle?: StyleProp; - iconName?: string; - isDestructor?: boolean; - isLink?: boolean; - labelComponent?: ReactNode; - labelStyle?: StyleProp; - leftComponent?: ReactNode; - messageValues?: Record; - onPress: () => void; - rightComponent?: ReactNode; - separator?: boolean; - separatorStyle?: StyleProp; - showArrow?: boolean; - testID: string; -}; -const MenuItem = ({ - centered, - chevronStyle, - containerStyle, - defaultMessage = '', - i18nId, - iconContainerStyle, - iconName, - isDestructor = false, - isLink = false, - labelComponent, - labelStyle, - leftComponent, - messageValues, - onPress, - rightComponent, - separator = true, - separatorStyle, - showArrow = false, - testID, -}: MenuItemProps) => { - const theme = useTheme(); - const style = getStyleSheet(theme); - - let icon; - if (leftComponent) { - icon = leftComponent; - } else if (iconName) { - icon = ( - - ); - } - - let label; - if (labelComponent) { - label = labelComponent; - } else if (i18nId) { - label = ( - - ); - } - - return ( - - - - {icon && ( - - {icon} - - )} - - {label} - - {rightComponent} - {Boolean(showArrow) && ( - - )} - - {Boolean(separator) && ()} - - - ); -}; - -export default MenuItem; diff --git a/app/components/option_item/index.tsx b/app/components/option_item/index.tsx index 36c0d3095c..3daa260e21 100644 --- a/app/components/option_item/index.tsx +++ b/app/components/option_item/index.tsx @@ -98,6 +98,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { export type OptionItemProps = { action?: (React.Dispatch>)|((value: string | boolean) => void); + arrowStyle?: StyleProp; containerStyle?: StyleProp; description?: string; destructive?: boolean; @@ -117,6 +118,7 @@ export type OptionItemProps = { const OptionItem = ({ action, + arrowStyle, containerStyle, description, destructive, @@ -197,6 +199,7 @@ const OptionItem = ({ color={changeOpacity(theme.centerChannelColor, 0.32)} name='chevron-right' size={24} + style={arrowStyle} /> ); } else if (type === OptionType.REMOVE) { @@ -239,14 +242,14 @@ const OptionItem = ({ {type === OptionType.RADIO && radioComponent} {label} {Boolean(description) && {description} diff --git a/app/components/status_label/index.tsx b/app/components/status_label/index.tsx index 8cc7e0c300..9d8015b131 100644 --- a/app/components/status_label/index.tsx +++ b/app/components/status_label/index.tsx @@ -2,24 +2,25 @@ // See LICENSE.txt for license information. import React from 'react'; -import {TextStyle} from 'react-native'; +import {StyleProp, TextStyle} from 'react-native'; import FormattedText from '@components/formatted_text'; import {General} from '@constants'; import {useTheme} from '@context/theme'; import {t} from '@i18n'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; +import {typography} from '@utils/typography'; type StatusLabelProps = { status?: string; - labelStyle?: TextStyle; + labelStyle?: StyleProp; } const getStyleSheet = makeStyleSheetFromTheme((theme) => { return { label: { color: changeOpacity(theme.centerChannelColor, 0.5), - fontSize: 17, + ...typography('Body', 200), textAlignVertical: 'center', includeFontPadding: false, }, diff --git a/app/database/operator/base_data_operator/index.ts b/app/database/operator/base_data_operator/index.ts index f9a59d2c58..631cf60e6d 100644 --- a/app/database/operator/base_data_operator/index.ts +++ b/app/database/operator/base_data_operator/index.ts @@ -93,8 +93,6 @@ export default class BaseDataOperator { // We found a record in the database that matches this element; hence, we'll proceed for an UPDATE operation if (existingRecord) { - // const existingRecord = createOrUpdateRaws[findIndex]; - // Some raw value has an update_at field. We'll proceed to update only if the update_at value is different from the record's value in database const updateRecords = getValidRecordsForUpdate({ tableName, @@ -125,8 +123,7 @@ export default class BaseDataOperator { * @param {RawValue[]} prepareRecord.createRaws * @param {RawValue[]} prepareRecord.updateRaws * @param {Model[]} prepareRecord.deleteRaws - * @param {(TransformerArgs) => Promise;} prepareRecord.composer - * @throws {DataOperatorException} + * @param {(TransformerArgs) => Promise;} transformer * @returns {Promise} */ prepareRecords = async ({tableName, createRaws, deleteRaws, updateRaws, transformer}: OperationArgs): Promise => { @@ -184,7 +181,6 @@ export default class BaseDataOperator { * batchRecords: Accepts an instance of Database (either Default or Server) and an array of * prepareCreate/prepareUpdate 'models' and executes the actions on the database. * @param {Array} models - * @throws {DataOperatorException} * @returns {Promise} */ async batchRecords(models: Model[]): Promise { diff --git a/app/database/operator/server_data_operator/handlers/group.ts b/app/database/operator/server_data_operator/handlers/group.ts index 6ceab3d804..0a64dd2e7f 100644 --- a/app/database/operator/server_data_operator/handlers/group.ts +++ b/app/database/operator/server_data_operator/handlers/group.ts @@ -28,7 +28,6 @@ const GroupHandler = (superclass: any) => class extends superclass implements Gr * handleGroups: Handler responsible for the Create/Update operations occurring on the Group table from the 'Server' schema * * @param {HandleGroupArgs} - * @throws DataOperatorException * @returns {Promise} */ handleGroups = async ({groups, prepareRecordsOnly = true}: HandleGroupArgs): Promise => { @@ -111,7 +110,6 @@ const GroupHandler = (superclass: any) => class extends superclass implements Gr * handleGroupMembershipsForMember: Handler responsible for the Create/Update operations occurring on the GroupMembership table from the 'Server' schema * * @param {HandleGroupMembershipForMemberArgs} - * @throws DataOperatorException * @returns {Promise} */ handleGroupMembershipsForMember = async ({userId, groups, prepareRecordsOnly = true}: HandleGroupMembershipForMemberArgs): Promise => { @@ -169,7 +167,6 @@ const GroupHandler = (superclass: any) => class extends superclass implements Gr * handleGroupTeamsForTeam: Handler responsible for the Create/Update operations occurring on the GroupTeam table from the 'Server' schema * * @param {HandleGroupTeamsForTeamArgs} - * @throws DataOperatorException * @returns {Promise} */ handleGroupTeamsForTeam = async ({teamId, groups, prepareRecordsOnly = true}: HandleGroupTeamsForTeamArgs): Promise => { diff --git a/app/screens/about/server_version.tsx b/app/screens/about/server_version.tsx deleted file mode 100644 index faf0e67290..0000000000 --- a/app/screens/about/server_version.tsx +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; - -import FormattedText from '@components/formatted_text'; -import {useTheme} from '@context/theme'; -import {t} from '@i18n'; -import {makeStyleSheetFromTheme} from '@utils/theme'; - -type ServerVersionProps = { - config: ClientConfig; -} - -const ServerVersion = ({config}: ServerVersionProps) => { - const buildNumber = config.BuildNumber; - const version = config.Version; - const theme = useTheme(); - const style = getStyleSheet(theme); - - let id = t('mobile.about.serverVersion'); - let defaultMessage = 'Server Version: {version} (Build {number})'; - let values: {version: string; number?: string} = { - version, - number: buildNumber, - }; - - if (buildNumber === version) { - id = t('mobile.about.serverVersionNoBuild'); - defaultMessage = 'Server Version: {version}'; - values = { - version, - number: undefined, - }; - } - return ( - - ); -}; - -const getStyleSheet = makeStyleSheetFromTheme((theme) => { - return { - info: { - color: theme.centerChannelColor, - fontSize: 16, - lineHeight: 19, - }, - }; -}); - -export default ServerVersion; diff --git a/app/screens/home/account/components/options/custom_status/custom_label.tsx b/app/screens/home/account/components/options/custom_status/custom_label.tsx index a430c85e4a..4ea11bc4e8 100644 --- a/app/screens/home/account/components/options/custom_status/custom_label.tsx +++ b/app/screens/home/account/components/options/custom_status/custom_label.tsx @@ -8,6 +8,7 @@ import {View} from 'react-native'; import ClearButton from '@components/custom_status/clear_button'; import CustomStatusExpiry from '@components/custom_status/custom_status_expiry'; import FormattedText from '@components/formatted_text'; +import {useTheme} from '@context/theme'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import CustomStatusText from './custom_status_text'; @@ -16,9 +17,8 @@ type CustomLabelProps = { customStatus: UserCustomStatus; isCustomStatusExpirySupported: boolean; isStatusSet: boolean; - showRetryMessage: boolean; - theme: Theme; onClearCustomStatus: () => void; + showRetryMessage: boolean; }; const getStyleSheet = makeStyleSheetFromTheme((theme) => { @@ -30,6 +30,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { }, customStatusTextContainer: { width: '70%', + marginLeft: 16, }, customStatusExpiryText: { paddingTop: 3, @@ -43,14 +44,14 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { }; }); -const CustomLabel = ({customStatus, isCustomStatusExpirySupported, isStatusSet, onClearCustomStatus, showRetryMessage, theme}: CustomLabelProps) => { - const style = getStyleSheet(theme); +const CustomLabel = ({customStatus, isCustomStatusExpirySupported, isStatusSet, onClearCustomStatus, showRetryMessage}: CustomLabelProps) => { + const theme = useTheme(); + const styles = getStyleSheet(theme); return ( <> - + @@ -58,7 +59,7 @@ const CustomLabel = ({customStatus, isCustomStatusExpirySupported, isStatusSet, )} {isStatusSet && ( - + { @@ -22,7 +22,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { }; }); -const CustomStatusEmoji = ({emoji, isStatusSet, theme}: CustomStatusEmojiProps) => { +const CustomStatusEmoji = ({emoji, isStatusSet}: CustomStatusEmojiProps) => { + const theme = useTheme(); const styles = getStyleSheet(theme); return ( diff --git a/app/screens/home/account/components/options/custom_status/custom_status_text.tsx b/app/screens/home/account/components/options/custom_status/custom_status_text.tsx index 35de980244..8ffddffe0f 100644 --- a/app/screens/home/account/components/options/custom_status/custom_status_text.tsx +++ b/app/screens/home/account/components/options/custom_status/custom_status_text.tsx @@ -5,27 +5,33 @@ import React from 'react'; import CustomText from '@components/custom_status/custom_status_text'; import FormattedText from '@components/formatted_text'; +import {useTheme} from '@context/theme'; import {makeStyleSheetFromTheme} from '@utils/theme'; +import {typography} from '@utils/typography'; type CustomStatusTextProps = { customStatus?: UserCustomStatus; isStatusSet: boolean; - theme: Theme; }; const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ text: { color: theme.centerChannelColor, + ...typography('Body', 200), }, })); -const CustomStatusText = ({isStatusSet, customStatus, theme}: CustomStatusTextProps) => { +const CustomStatusText = ({isStatusSet, customStatus}: CustomStatusTextProps) => { + const theme = useTheme(); + const styles = getStyleSheet(theme); + let text: React.ReactNode | string; text = ( ); @@ -33,7 +39,6 @@ const CustomStatusText = ({isStatusSet, customStatus, theme}: CustomStatusTextPr text = customStatus.text; } - const styles = getStyleSheet(theme); return ( { + return { + label: { + color: theme.centerChannelColor, + ...typography('Body', 200), + textAlignVertical: 'center', + includeFontPadding: false, + }, + body: { + flexDirection: 'row', + marginVertical: 18, + }, + }; +}); + type CustomStatusProps = { isCustomStatusExpirySupported: boolean; isTablet: boolean; @@ -35,6 +51,7 @@ const CustomStatus = ({isCustomStatusExpirySupported, isTablet, currentUser}: Cu const customStatus = getUserCustomStatus(currentUser); const isCustomStatusExpired = checkCustomStatusIsExpired(currentUser); const isStatusSet = !isCustomStatusExpired && (customStatus?.text || customStatus?.emoji); + const styles = getStyleSheet(theme); useEffect(() => { const onSetCustomStatusError = () => { @@ -68,27 +85,23 @@ const CustomStatus = ({isCustomStatusExpirySupported, isTablet, currentUser}: Cu }), [isTablet]); return ( - + + - } - leftComponent={ - } - separator={false} - onPress={goToCustomStatusScreen} - /> + + ); }; diff --git a/app/screens/home/account/components/options/index.tsx b/app/screens/home/account/components/options/index.tsx index 587b38952a..f910870b65 100644 --- a/app/screens/home/account/components/options/index.tsx +++ b/app/screens/home/account/components/options/index.tsx @@ -36,13 +36,12 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { divider: { backgroundColor: changeOpacity(theme.centerChannelColor, 0.2), height: 1, - marginHorizontal: 15, + width: '90%', + alignSelf: 'center', + marginVertical: 8, }, - menuLabel: { - color: theme.centerChannelColor, - fontSize: 16, - lineHeight: 24, - fontFamily: 'OpenSans', + group: { + paddingLeft: 16, }, }; }); @@ -64,37 +63,29 @@ const AccountOptions = ({user, enableCustomUserStatuses, isCustomStatusExpirySup }} > - - {enableCustomUserStatuses && - } + + + {enableCustomUserStatuses && + } + - - {/* */} - + + + + - + + + ); diff --git a/app/screens/home/account/components/options/logout/index.tsx b/app/screens/home/account/components/options/logout/index.tsx index 184b3f0da2..29a2c4b8e1 100644 --- a/app/screens/home/account/components/options/logout/index.tsx +++ b/app/screens/home/account/components/options/logout/index.tsx @@ -3,75 +3,48 @@ import React, {useCallback} from 'react'; import {useIntl} from 'react-intl'; -import {TextStyle, View} from 'react-native'; import {logout} from '@actions/remote/session'; -import FormattedText from '@components/formatted_text'; -import MenuItem from '@components/menu_item'; +import OptionItem from '@components/option_item'; import {useServerDisplayName, useServerUrl} from '@context/server'; +import {useTheme} from '@context/theme'; import {alertServerLogout} from '@utils/server'; import {preventDoubleTap} from '@utils/tap'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; +import {typography} from '@utils/typography'; -type Props = { - style: TextStyle; - theme: Theme; -} +const getStyleSheet = makeStyleSheetFromTheme((theme) => { + return { + desc: { + color: changeOpacity(theme.centerChannelColor, 0.64), + ...typography('Body', 75), + }, + }; +}); -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - label: { - color: theme.dndIndicator, - marginTop: 5, - }, - logOutFrom: { - color: changeOpacity(theme.centerChannelColor, 0.64), - fontSize: 12, - height: 30, - lineHeight: 16, - fontFamily: 'OpenSans', - }, -})); - -const Settings = ({style, theme}: Props) => { +const LogOut = () => { + const theme = useTheme(); const styles = getStyleSheet(theme); const intl = useIntl(); const serverUrl = useServerUrl(); const serverDisplayName = useServerDisplayName(); const onLogout = useCallback(preventDoubleTap(() => { - alertServerLogout( - serverDisplayName, - () => { - logout(serverUrl); - }, - intl, - ); + alertServerLogout(serverDisplayName, () => logout(serverUrl), intl); }), [serverDisplayName, serverUrl, intl]); return ( - - - - - )} - onPress={onLogout} - separator={false} + ); }; -export default Settings; +export default LogOut; diff --git a/app/screens/home/account/components/options/settings/index.tsx b/app/screens/home/account/components/options/settings/index.tsx index e2134be8a7..fd2f0bf986 100644 --- a/app/screens/home/account/components/options/settings/index.tsx +++ b/app/screens/home/account/components/options/settings/index.tsx @@ -3,47 +3,29 @@ import React, {useCallback} from 'react'; import {useIntl} from 'react-intl'; -import {TextStyle} from 'react-native'; -import FormattedText from '@components/formatted_text'; -import MenuItem from '@components/menu_item'; +import OptionItem from '@components/option_item'; import Screens from '@constants/screens'; import {showModal} from '@screens/navigation'; -import {logInfo} from '@utils/log'; import {preventDoubleTap} from '@utils/tap'; -type Props = { - isTablet: boolean; - style: TextStyle; -} - -const Settings = ({isTablet, style}: Props) => { +const Settings = () => { const intl = useIntl(); const openSettings = useCallback(preventDoubleTap(() => { - if (isTablet) { - //todo: https://mattermost.atlassian.net/browse/MM-39711 - logInfo('Settings on tablets need to be figured out and implemented - @Avinash'); - } showModal( Screens.SETTINGS, intl.formatMessage({id: 'mobile.screen.settings', defaultMessage: 'Settings'}), ); - }), [isTablet]); + }), []); return ( - - } - onPress={openSettings} - separator={false} + ); }; diff --git a/app/screens/home/account/components/options/user_presence/index.tsx b/app/screens/home/account/components/options/user_presence/index.tsx index f652036220..09711708f0 100644 --- a/app/screens/home/account/components/options/user_presence/index.tsx +++ b/app/screens/home/account/components/options/user_presence/index.tsx @@ -3,36 +3,54 @@ import React, {useCallback} from 'react'; import {useIntl} from 'react-intl'; -import {TextStyle} from 'react-native'; +import {TouchableOpacity, View} from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; import {setStatus} from '@actions/remote/user'; -import MenuItem from '@components/menu_item'; import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item'; import StatusLabel from '@components/status_label'; import UserStatusIndicator from '@components/user_status'; import General from '@constants/general'; import {useServerUrl} from '@context/server'; +import {useTheme} from '@context/theme'; import {bottomSheet, dismissBottomSheet, dismissModal} from '@screens/navigation'; import {bottomSheetSnapPoint} from '@utils/helpers'; import {preventDoubleTap} from '@utils/tap'; -import {changeOpacity} from '@utils/theme'; +import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; +import {typography} from '@utils/typography'; import {confirmOutOfOfficeDisabled} from '@utils/user'; import type UserModel from '@typings/database/models/servers/user'; -type Props = { - currentUser: UserModel; - style: TextStyle; - theme: Theme; -}; +const getStyleSheet = makeStyleSheetFromTheme((theme) => { + return { + label: { + color: theme.centerChannelColor, + ...typography('Body', 200), + textAlignVertical: 'center', + includeFontPadding: false, + }, + body: { + flexDirection: 'row', + marginTop: 18, + }, + spacer: { + marginLeft: 16, + }, + }; +}); const {OUT_OF_OFFICE, OFFLINE, AWAY, ONLINE, DND} = General; -const UserStatus = ({currentUser, style, theme}: Props) => { +type Props = { + currentUser: UserModel; +}; +const UserStatus = ({currentUser}: Props) => { const intl = useIntl(); const insets = useSafeAreaInsets(); const serverUrl = useServerUrl(); + const theme = useTheme(); + const styles = getStyleSheet(theme); const handleSetStatus = useCallback(preventDoubleTap(() => { const renderContent = () => { @@ -47,7 +65,7 @@ const UserStatus = ({currentUser, style, theme}: Props) => { id: 'mobile.set_status.online', defaultMessage: 'Online', })} - textStyles={style} + textStyles={styles.label} /> { id: 'mobile.set_status.away', defaultMessage: 'Away', })} - textStyles={style} + textStyles={styles.label} /> { id: 'mobile.set_status.dnd', defaultMessage: 'Do Not Disturb', })} - textStyles={style} + textStyles={styles.label} /> { id: 'mobile.set_status.offline', defaultMessage: 'Offline', })} - textStyles={style} + textStyles={styles.label} /> ); @@ -119,23 +137,20 @@ const UserStatus = ({currentUser, style, theme}: Props) => { }, []); return ( - - } - leftComponent={ + + - } - onPress={handleSetStatus} - separator={false} - testID='account.status.action' - /> + + + ); }; diff --git a/app/screens/home/account/components/options/your_profile/index.tsx b/app/screens/home/account/components/options/your_profile/index.tsx index 4bbdca99c4..e49f29e36d 100644 --- a/app/screens/home/account/components/options/your_profile/index.tsx +++ b/app/screens/home/account/components/options/your_profile/index.tsx @@ -3,10 +3,9 @@ import React, {useCallback} from 'react'; import {useIntl} from 'react-intl'; -import {DeviceEventEmitter, TextStyle} from 'react-native'; +import {DeviceEventEmitter} from 'react-native'; -import FormattedText from '@components/formatted_text'; -import MenuItem from '@components/menu_item'; +import OptionItem from '@components/option_item'; import {Events, Screens} from '@constants'; import {ACCOUNT_OUTLINE_IMAGE} from '@constants/profile'; import {showModal} from '@screens/navigation'; @@ -14,11 +13,10 @@ import {preventDoubleTap} from '@utils/tap'; type Props = { isTablet: boolean; - style: TextStyle; theme: Theme; } -const YourProfile = ({isTablet, style, theme}: Props) => { +const YourProfile = ({isTablet, theme}: Props) => { const intl = useIntl(); const openProfile = useCallback(preventDoubleTap(() => { if (isTablet) { @@ -32,18 +30,12 @@ const YourProfile = ({isTablet, style, theme}: Props) => { }), [isTablet, theme]); return ( - - } - onPress={openProfile} - separator={false} + ); }; diff --git a/app/screens/home/search/initial/modifiers/show_more.tsx b/app/screens/home/search/initial/modifiers/show_more.tsx index dc84920b14..73bd533b5a 100644 --- a/app/screens/home/search/initial/modifiers/show_more.tsx +++ b/app/screens/home/search/initial/modifiers/show_more.tsx @@ -1,9 +1,9 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React from 'react'; +import {useIntl} from 'react-intl'; -import FormattedText from '@components/formatted_text'; -import MenuItem from '@components/menu_item'; +import OptionItem from '@components/option_item'; import {useTheme} from '@context/theme'; import {t} from '@i18n'; import {makeStyleSheetFromTheme} from '@utils/theme'; @@ -26,7 +26,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { const ShowMoreButton = ({onPress, showMore}: ShowMoreButtonProps) => { const theme = useTheme(); - const style = getStyleSheet(theme); + const intl = useIntl(); + const styles = getStyleSheet(theme); let id = t('mobile.search.show_more'); let defaultMessage = 'Show more'; @@ -36,17 +37,12 @@ const ShowMoreButton = ({onPress, showMore}: ShowMoreButtonProps) => { } return ( - - } - onPress={onPress} - separator={false} + ); }; diff --git a/app/screens/post_options/post_options.tsx b/app/screens/post_options/post_options.tsx index 20fb1c036d..a8b978689d 100644 --- a/app/screens/post_options/post_options.tsx +++ b/app/screens/post_options/post_options.tsx @@ -5,7 +5,7 @@ import {useManagedConfig} from '@mattermost/react-native-emm'; import React from 'react'; import {CopyPermalinkOption, FollowThreadOption, ReplyOption, SaveOption} from '@components/common_post_options'; -import {ITEM_HEIGHT} from '@components/menu_item'; +import {ITEM_HEIGHT} from '@components/option_item'; import {Screens} from '@constants'; import useNavButtonPressed from '@hooks/navigation_button_pressed'; import BottomSheet from '@screens/bottom_sheet'; diff --git a/app/screens/settings/about/tos_privacy.tsx b/app/screens/settings/about/tos_privacy.tsx index 69110ec624..1d365f9369 100644 --- a/app/screens/settings/about/tos_privacy.tsx +++ b/app/screens/settings/about/tos_privacy.tsx @@ -8,18 +8,37 @@ import FormattedText from '@components/formatted_text'; import {useTheme} from '@context/theme'; import {t} from '@i18n'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; +import {typography} from '@utils/typography'; + +const getStyleSheet = makeStyleSheetFromTheme((theme) => { + return { + noticeLink: { + color: theme.linkColor, + ...typography('Body', 50), + }, + footerText: { + color: changeOpacity(theme.centerChannelColor, 0.5), + ...typography('Body', 50), + marginBottom: 10, + }, + hyphenText: { + marginBottom: 0, + }, + }; +}); type TosPrivacyContainerProps = { config: ClientConfig; onPressTOS: () => void; onPressPrivacyPolicy: () => void; } - const TosPrivacyContainer = ({config, onPressTOS, onPressPrivacyPolicy}: TosPrivacyContainerProps) => { - const hasTermsOfServiceLink = config.TermsOfServiceLink; - const hasPrivacyPolicyLink = config.PrivacyPolicyLink; const theme = useTheme(); const style = getStyleSheet(theme); + + const hasTermsOfServiceLink = Boolean(config.TermsOfServiceLink); + const hasPrivacyPolicyLink = Boolean(config.PrivacyPolicyLink); + return ( <> {hasTermsOfServiceLink && ( @@ -49,23 +68,4 @@ const TosPrivacyContainer = ({config, onPressTOS, onPressPrivacyPolicy}: TosPriv ); }; -const getStyleSheet = makeStyleSheetFromTheme((theme) => { - return { - noticeLink: { - color: theme.linkColor, - fontSize: 11, - lineHeight: 13, - }, - footerText: { - color: changeOpacity(theme.centerChannelColor, 0.5), - fontSize: 11, - lineHeight: 13, - marginBottom: 10, - }, - hyphenText: { - marginBottom: 0, - }, - }; -}); - export default TosPrivacyContainer; diff --git a/app/screens/settings/config.ts b/app/screens/settings/config.ts index 4e1569a6b4..6b39e0ac2e 100644 --- a/app/screens/settings/config.ts +++ b/app/screens/settings/config.ts @@ -16,81 +16,87 @@ export const getSaveButton = (buttonId: string, intl: IntlShape, color: string) ...typography('Body', 100, 'SemiBold'), }); -export const SettingOptionConfig = { +type SettingConfigDetails = { + defaultMessage?: string; + i18nId?: string; + icon?: string; + testID?: string; +} + +export const SettingOptionConfig: Record = { notification: { defaultMessage: 'Notifications', i18nId: t('general_settings.notifications'), - iconName: 'bell-outline', + icon: 'bell-outline', testID: 'general_settings.notifications', }, display: { defaultMessage: 'Display', i18nId: t('general_settings.display'), - iconName: 'layers-outline', + icon: 'layers-outline', testID: 'general_settings.display', }, advanced_settings: { defaultMessage: 'Advanced Settings', i18nId: t('general_settings.advanced_settings'), - iconName: 'tune', + icon: 'tune', testID: 'general_settings.advanced', }, about: { defaultMessage: 'About {appTitle}', i18nId: t('general_settings.about'), - iconName: 'information-outline', + icon: 'information-outline', testID: 'general_settings.about', }, help: { defaultMessage: 'Help', i18nId: t('general_settings.help'), testID: 'general_settings.help', - showArrow: false, }, }; -export const NotificationsOptionConfig = { +export const NotificationsOptionConfig: Record = { mentions: { - iconName: 'at', + icon: 'at', testID: 'notification_settings.mentions_replies', }, push_notification: { defaultMessage: 'Push Notifications', i18nId: t('notification_settings.mobile'), - iconName: 'cellphone', + icon: 'cellphone', testID: 'notification_settings.push_notification', }, email: { defaultMessage: 'Email', i18nId: t('notification_settings.email'), - iconName: 'email-outline', + icon: 'email-outline', testID: 'notification_settings.email', }, automatic_dm_replies: { defaultMessage: 'Automatic replies', i18nId: t('notification_settings.ooo_auto_responder'), - iconName: 'reply-outline', + icon: 'reply-outline', testID: 'notification_settings.automatic_dm_replies', }, }; -export const DisplayOptionConfig = { +export const DisplayOptionConfig: Record = { clock: { defaultMessage: 'Clock Display', i18nId: t('mobile.display_settings.clockDisplay'), - iconName: 'clock-outline', + icon: 'clock-outline', testID: 'display_settings.clock', }, theme: { defaultMessage: 'Theme', i18nId: t('mobile.display_settings.theme'), - iconName: 'palette-outline', + icon: 'palette-outline', testID: 'display_settings.theme', }, timezone: { defaultMessage: 'Timezone', i18nId: t('mobile.display_settings.timezone'), - iconName: 'globe', + icon: 'globe', testID: 'display_settings.timezone', }, }; diff --git a/app/screens/settings/display/display.tsx b/app/screens/settings/display/display.tsx index f2d0ac97b1..1b144e66c7 100644 --- a/app/screens/settings/display/display.tsx +++ b/app/screens/settings/display/display.tsx @@ -3,7 +3,6 @@ import React, {useMemo} from 'react'; import {useIntl} from 'react-intl'; -import {StyleSheet} from 'react-native'; import {Screens} from '@constants'; import {useTheme} from '@context/theme'; @@ -14,7 +13,6 @@ import {getUserTimezoneProps} from '@utils/user'; import SettingContainer from '../setting_container'; import SettingItem from '../setting_item'; -import SettingRowLabel from '../setting_row_label'; import type UserModel from '@typings/database/models/servers/user'; @@ -40,12 +38,6 @@ const TIMEZONE_FORMAT = [ }, ]; -const styles = StyleSheet.create({ - title: { - textTransform: 'capitalize', - }, -}); - type DisplayProps = { currentUser: UserModel; hasMilitaryTimeFormat: boolean; @@ -83,32 +75,19 @@ const Display = ({currentUser, hasMilitaryTimeFormat, isThemeSwitchingEnabled, i - } + info={theme.type!} /> )} - } + info={intl.formatMessage(hasMilitaryTimeFormat ? TIME_FORMAT[1] : TIME_FORMAT[0])} /> {isTimezoneEnabled && ( - } + info={intl.formatMessage(timezone.useAutomaticTimezone ? TIMEZONE_FORMAT[0] : TIMEZONE_FORMAT[1])} /> )} diff --git a/app/screens/settings/notification_auto_responder/notification_auto_responder.tsx b/app/screens/settings/notification_auto_responder/notification_auto_responder.tsx index e7f29cadfd..3c173b095b 100644 --- a/app/screens/settings/notification_auto_responder/notification_auto_responder.tsx +++ b/app/screens/settings/notification_auto_responder/notification_auto_responder.tsx @@ -4,7 +4,7 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {useIntl} from 'react-intl'; -import {updateMe} from '@actions/remote/user'; +import {fetchStatusInBatch, updateMe} from '@actions/remote/user'; import FloatingTextInput from '@components/floating_text_input_label'; import FormattedText from '@components/formatted_text'; import {General} from '@constants'; @@ -88,8 +88,9 @@ const NotificationAutoResponder = ({currentUser, componentId}: NotificationAutoR auto_responder_message: autoResponderMessage, }, }); + fetchStatusInBatch(serverUrl, currentUser.id); close(); - }, [serverUrl, autoResponderActive, autoResponderMessage, notifyProps]); + }, [serverUrl, autoResponderActive, autoResponderMessage, notifyProps, currentUser.id]); useEffect(() => { const enabled = initialAutoResponderActive !== autoResponderActive || initialOOOMsg !== autoResponderMessage; @@ -120,7 +121,6 @@ const NotificationAutoResponder = ({currentUser, componentId}: NotificationAutoR allowFontScaling={true} autoCapitalize='none' autoCorrect={false} - blurOnSubmit={true} containerStyle={styles.textInputContainer} keyboardAppearance={getKeyboardAppearanceFromTheme(theme)} label={intl.formatMessage(label)} @@ -128,7 +128,7 @@ const NotificationAutoResponder = ({currentUser, componentId}: NotificationAutoR onChangeText={setAutoResponderMessage} placeholder={intl.formatMessage(label)} placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.4)} - returnKeyType='done' + returnKeyType='default' textAlignVertical='top' textInputStyle={styles.input} theme={theme} diff --git a/app/screens/settings/notifications/notifications.tsx b/app/screens/settings/notifications/notifications.tsx index e5e5155304..f0cfc37fd9 100644 --- a/app/screens/settings/notifications/notifications.tsx +++ b/app/screens/settings/notifications/notifications.tsx @@ -7,7 +7,6 @@ import {useIntl} from 'react-intl'; import {General, Screens} from '@constants'; import {t} from '@i18n'; import {goToScreen} from '@screens/navigation'; -import SettingRowLabel from '@screens/settings/setting_row_label'; import {getEmailInterval, getEmailIntervalTexts, getNotificationProps} from '@utils/user'; import SettingContainer from '../setting_container'; @@ -91,10 +90,12 @@ const Notifications = ({ return ( - } + info={intl.formatMessage(getEmailIntervalTexts(emailIntervalPref))} /> {enableAutoResponder && ( - } + info={currentUser.status === General.OUT_OF_OFFICE && notifyProps.auto_responder_active === 'true' ? 'On' : 'Off'} /> )} diff --git a/app/screens/settings/setting_item.tsx b/app/screens/settings/setting_item.tsx index 075d24bd26..8fcb10fe9a 100644 --- a/app/screens/settings/setting_item.tsx +++ b/app/screens/settings/setting_item.tsx @@ -2,10 +2,12 @@ // See LICENSE.txt for license information. import React from 'react'; +import {useIntl} from 'react-intl'; import {Platform} from 'react-native'; -import MenuItem, {MenuItemProps} from '@components/menu_item'; +import OptionItem, {OptionItemProps} from '@components/option_item'; import {useTheme} from '@context/theme'; +import SettingSeparator from '@screens/settings/settings_separator'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import {typography} from '@utils/typography'; @@ -15,7 +17,8 @@ type SettingsConfig = keyof typeof SettingOptionConfig | keyof typeof Notificati type SettingOptionProps = { optionName: SettingsConfig; onPress: () => void; -} & Omit; + separator?: boolean; +} & Partial; const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { return { @@ -23,10 +26,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { color: theme.centerChannelColor, ...typography('Body', 200, 'Regular'), }, - separatorStyle: { - width: '91%', - alignSelf: 'center', - }, chevronStyle: { marginRight: 14, color: changeOpacity(theme.centerChannelColor, 0.32), @@ -34,21 +33,35 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { }; }); -const SettingItem = ({onPress, optionName, ...rest}: SettingOptionProps) => { +const SettingItem = ({ + info, + onPress, + optionName, + separator = true, + ...props +}: SettingOptionProps) => { const theme = useTheme(); + const intl = useIntl(); const styles = getStyleSheet(theme); - const props = {...rest, ...Options[optionName]} as unknown as Omit; + const config = Options[optionName]; + + const label = props.label || intl.formatMessage({id: config.i18nId, defaultMessage: config.defaultMessage}); return ( - + <> + + {separator && } + ); }; diff --git a/app/screens/settings/setting_row_label.tsx b/app/screens/settings/setting_row_label.tsx deleted file mode 100644 index 3cdc2341cd..0000000000 --- a/app/screens/settings/setting_row_label.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; -import {Platform, StyleProp, Text, TextStyle} from 'react-native'; - -import {useTheme} from '@context/theme'; -import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; -import {typography} from '@utils/typography'; - -const getStyleSheet = makeStyleSheetFromTheme((theme) => { - return { - rightLabel: { - color: changeOpacity(theme.centerChannelColor, 0.56), - ...typography('Body', 100, 'Regular'), - alignSelf: 'center', - ...Platform.select({ - android: { - marginRight: 20, - }, - }), - }, - }; -}); - -type SettingRowLabelProps = { - text: string; - textStyle?: StyleProp; -} -const SettingRowLabel = ({text, textStyle}: SettingRowLabelProps) => { - const theme = useTheme(); - const styles = getStyleSheet(theme); - - return ( - - {text} - - - ); -}; - -export default SettingRowLabel; diff --git a/app/screens/settings/settings.tsx b/app/screens/settings/settings.tsx index 83ae77238d..d01cdf388c 100644 --- a/app/screens/settings/settings.tsx +++ b/app/screens/settings/settings.tsx @@ -135,18 +135,20 @@ const Settings = ({componentId, helpLink, showHelp, siteName}: SettingsProps) => optionName='advanced_settings' /> {Platform.OS === 'android' && } {showHelp && } diff --git a/app/screens/snack_bar/index.tsx b/app/screens/snack_bar/index.tsx index 96eb867856..2c75d2e949 100644 --- a/app/screens/snack_bar/index.tsx +++ b/app/screens/snack_bar/index.tsx @@ -234,10 +234,10 @@ const SnackBar = ({barType, componentId, onAction, sourceScreen}: SnackBarProps) > {config.canUndo && onAction && ( diff --git a/app/screens/thread_options/thread_options.tsx b/app/screens/thread_options/thread_options.tsx index ec6d0d218a..e1bc234b03 100644 --- a/app/screens/thread_options/thread_options.tsx +++ b/app/screens/thread_options/thread_options.tsx @@ -7,7 +7,7 @@ import {View} from 'react-native'; import {CopyPermalinkOption, FollowThreadOption, ReplyOption, SaveOption} from '@components/common_post_options'; import FormattedText from '@components/formatted_text'; -import {ITEM_HEIGHT} from '@components/menu_item'; +import {ITEM_HEIGHT} from '@components/option_item'; import {Screens} from '@constants'; import {useTheme} from '@context/theme'; import {useIsTablet} from '@hooks/device';