[FIX] Wrong styling on E2E encryption banner (#2767)

* [FIX] Wrong styling on E2E encryption banner

* [FIX] Wrong styling on E2E encryption banner

* [FIX] Wrong styling on E2E encryption banner

* [FIX] Wrong styling on E2E encryption banner (#2767)

* Updated SortDropdown, ListHeader, ListItem and added stories for List.Item

* Updated SortDropdown

* Removed unused component

* Updated List.Item and stories

* Reverted unnecessary changes and updated ListItem stories

* Fix minor indentation

* Stop breaking Touch's default underlay color

* Fix indentation

* Remove falsy comparison from render

* Fix left icon

* Use List.Item on OmnichannelStatus

* Add missing separator

* Lint

* Fix sort dropdown

* Remove unnecessary styles

* Fix detox

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Gerzon Z 2021-01-21 15:52:26 -04:00 committed by GitHub
parent 0fdb8f2e46
commit bd09cd32a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 225 additions and 344 deletions

View File

@ -6796,7 +6796,7 @@ exports[`Storyshots List with black theme 1`] = `
</RNCSafeAreaView>
`;
exports[`Storyshots List with custom color 1`] = `
exports[`Storyshots List with custom colors 1`] = `
<RCTScrollView
contentContainerStyle={
Object {
@ -6893,6 +6893,65 @@ exports[`Storyshots List with custom color 1`] = `
]
}
/>
<View
style={
Array [
Object {
"alignItems": "center",
"flex": 1,
"flexDirection": "row",
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
Object {
"height": 92,
},
]
}
>
<View
style={
Object {
"flex": 1,
"justifyContent": "center",
}
}
>
<Text
numberOfLines={1}
style={
Array [
Object {
"backgroundColor": "transparent",
"fontFamily": "System",
"fontSize": 16,
"fontWeight": "400",
"textAlign": "left",
},
Object {
"color": "white",
},
]
}
>
Press me!
</Text>
</View>
</View>
<View
style={
Array [
Object {
"height": 0.5,
},
undefined,
Object {
"backgroundColor": "#cbcbcc",
},
]
}
/>
</View>
</RCTScrollView>
`;

View File

@ -35,6 +35,7 @@ export const themes = {
auxiliaryText: '#9ca2a8',
infoText: '#6d6d72',
tintColor: '#1d74f5',
tintActive: '#549df9',
auxiliaryTintColor: '#6C727A',
actionTintColor: '#1d74f5',
separatorColor: '#cbcbcc',
@ -80,6 +81,7 @@ export const themes = {
auxiliaryText: '#9297a2',
infoText: '#6D6D72',
tintColor: '#1d74f5',
tintActive: '#549df9',
auxiliaryTintColor: '#f9f9f9',
actionTintColor: '#1d74f5',
separatorColor: '#2b2b2d',
@ -125,6 +127,7 @@ export const themes = {
auxiliaryText: '#b2b8c6',
infoText: '#6d6d72',
tintColor: '#1e9bfe',
tintActive: '#76b7fc',
auxiliaryTintColor: '#f9f9f9',
actionTintColor: '#1e9bfe',
separatorColor: '#272728',

View File

@ -1,9 +1,6 @@
import React from 'react';
import {
View,
Text,
StyleSheet,
I18nManager
View, Text, StyleSheet, I18nManager
} from 'react-native';
import PropTypes from 'prop-types';
@ -82,11 +79,12 @@ const Content = React.memo(({
));
const Button = React.memo(({
onPress, ...props
onPress, backgroundColor, underlayColor, ...props
}) => (
<Touch
onPress={() => onPress(props.title)}
style={{ backgroundColor: themes[props.theme].backgroundColor }}
style={{ backgroundColor: backgroundColor || themes[props.theme].backgroundColor }}
underlayColor={underlayColor}
enabled={!props.disabled}
theme={props.theme}
>
@ -99,7 +97,7 @@ const ListItem = React.memo(({ ...props }) => {
return <Button {...props} />;
}
return (
<View style={{ backgroundColor: themes[props.theme].backgroundColor }}>
<View style={{ backgroundColor: props.backgroundColor || themes[props.theme].backgroundColor }}>
<Content {...props} />
</View>
);
@ -107,7 +105,8 @@ const ListItem = React.memo(({ ...props }) => {
ListItem.propTypes = {
onPress: PropTypes.func,
theme: PropTypes.string
theme: PropTypes.string,
backgroundColor: PropTypes.string
};
ListItem.displayName = 'List.Item';
@ -137,7 +136,9 @@ Button.propTypes = {
title: PropTypes.string,
onPress: PropTypes.func,
disabled: PropTypes.bool,
theme: PropTypes.string
theme: PropTypes.string,
backgroundColor: PropTypes.string,
underlayColor: PropTypes.string
};
Button.defaultProps = {

View File

@ -1,12 +1,8 @@
import React, { memo, useState, useEffect } from 'react';
import {
View, Text, StyleSheet, Switch
} from 'react-native';
import { View, Switch } from 'react-native';
import PropTypes from 'prop-types';
import Touch from '../../../utils/touch';
import { CustomIcon } from '../../../lib/Icons';
import I18n from '../../../i18n';
import * as List from '../../../containers/List';
import styles from '../../../views/RoomsListView/styles';
import { themes, SWITCH_TRACK_COLOR } from '../../../constants/colors';
import { withTheme } from '../../../theme';
@ -36,19 +32,14 @@ const OmnichannelStatus = memo(({
};
return (
<Touch
<>
<List.Item
title='Omnichannel'
left={() => <List.Icon name='omnichannel' />}
color={themes[theme].auxiliaryText}
onPress={goQueue}
theme={theme}
style={{ backgroundColor: themes[theme].headerSecondaryBackground }}
>
<View
style={[
styles.dropdownContainerHeader,
{ borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor }
]}
>
<CustomIcon style={[styles.queueIcon, { color: themes[theme].auxiliaryText }]} size={22} name='omnichannel' />
<Text style={[styles.queueToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Omnichannel')}</Text>
right={() => (
<View style={styles.omnichannelRightContainer}>
{inquiryEnabled
? (
<UnreadBadge
@ -58,13 +49,15 @@ const OmnichannelStatus = memo(({
)
: null}
<Switch
style={styles.omnichannelToggle}
value={status}
trackColor={SWITCH_TRACK_COLOR}
onValueChange={toggleLivechat}
/>
</View>
</Touch>
)}
/>
<List.Separator />
</>
);
});

View File

@ -15,7 +15,7 @@ class Touch extends React.Component {
render() {
const {
children, onPress, theme, ...props
children, onPress, theme, underlayColor, ...props
} = this.props;
return (
@ -23,7 +23,7 @@ class Touch extends React.Component {
ref={this.getRef}
onPress={onPress}
activeOpacity={1}
underlayColor={themes[theme].bannerBackground}
underlayColor={underlayColor || themes[theme].bannerBackground}
rippleColor={themes[theme].bannerBackground}
{...props}
>
@ -36,7 +36,8 @@ class Touch extends React.Component {
Touch.propTypes = {
children: PropTypes.node,
onPress: PropTypes.func,
theme: PropTypes.string
theme: PropTypes.string,
underlayColor: PropTypes.string
};
export default Touch;

View File

@ -1,49 +0,0 @@
import React from 'react';
import { Text } from 'react-native';
import PropTypes from 'prop-types';
import { BorderlessButton } from 'react-native-gesture-handler';
import { withTheme } from '../../../theme';
import { CustomIcon } from '../../../lib/Icons';
import { themes } from '../../../constants/colors';
import I18n from '../../../i18n';
import styles from '../styles';
import { E2E_BANNER_TYPE } from '../../../lib/encryption/constants';
const Encryption = React.memo(({
searching,
goEncryption,
encryptionBanner,
theme
}) => {
if (searching > 0 || !encryptionBanner) {
return null;
}
let text = I18n.t('Save_Your_Encryption_Password');
if (encryptionBanner === E2E_BANNER_TYPE.REQUEST_PASSWORD) {
text = I18n.t('Enter_Your_E2E_Password');
}
return (
<BorderlessButton
style={[styles.encryptionButton, { backgroundColor: themes[theme].actionTintColor }]}
theme={theme}
onPress={goEncryption}
testID='listheader-encryption'
accessibilityLabel={text}
>
<CustomIcon name='encrypted' size={24} color={themes[theme].buttonText} style={styles.encryptionIcon} />
<Text style={[styles.encryptionText, { color: themes[theme].buttonText }]}>{text}</Text>
</BorderlessButton>
);
});
Encryption.propTypes = {
searching: PropTypes.bool,
goEncryption: PropTypes.func,
encryptionBanner: PropTypes.string,
theme: PropTypes.string
};
export default withTheme(Encryption);

View File

@ -1,45 +0,0 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import Touch from '../../../utils/touch';
import { CustomIcon } from '../../../lib/Icons';
import I18n from '../../../i18n';
import styles from '../styles';
import { themes } from '../../../constants/colors';
import { withTheme } from '../../../theme';
const Sort = React.memo(({
searching, sortBy, toggleSort, theme
}) => {
if (searching > 0) {
return null;
}
return (
<Touch
onPress={toggleSort}
theme={theme}
style={{ backgroundColor: themes[theme].headerSecondaryBackground }}
>
<View
style={[
styles.dropdownContainerHeader,
{ borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor }
]}
>
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort' />
<Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
</View>
</Touch>
);
});
Sort.propTypes = {
searching: PropTypes.bool,
sortBy: PropTypes.string,
theme: PropTypes.string,
toggleSort: PropTypes.func
};
export default withTheme(Sort);

View File

@ -1,8 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import Sort from './Sort';
import Encryption from './Encryption';
import { withTheme } from '../../../theme';
import I18n from '../../../i18n';
import * as List from '../../../containers/List';
import { E2E_BANNER_TYPE } from '../../../lib/encryption/constants';
import { themes } from '../../../constants/colors';
import OmnichannelStatus from '../../../ee/omnichannel/containers/OmnichannelStatus';
@ -15,14 +18,55 @@ const ListHeader = React.memo(({
queueSize,
inquiryEnabled,
encryptionBanner,
user
}) => (
user,
theme
}) => {
const sortTitle = I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') });
if (searching) {
return null;
}
return (
<>
<Encryption searching={searching} goEncryption={goEncryption} encryptionBanner={encryptionBanner} />
<Sort searching={searching} sortBy={sortBy} toggleSort={toggleSort} />
<OmnichannelStatus searching={searching} goQueue={goQueue} inquiryEnabled={inquiryEnabled} queueSize={queueSize} user={user} />
{encryptionBanner
? (
<>
<List.Item
title={
encryptionBanner === E2E_BANNER_TYPE.REQUEST_PASSWORD
? 'Enter_Your_E2E_Password'
: 'Save_Your_Encryption_Password'
}
left={() => <List.Icon name='encrypted' color={themes[theme].buttonText} />}
underlayColor={themes[theme].tintActive}
backgroundColor={themes[theme].actionTintColor}
color={themes[theme].buttonText}
onPress={goEncryption}
testID='listheader-encryption'
/>
<List.Separator />
</>
));
)
: null}
<List.Item
title={sortTitle}
left={() => <List.Icon name='sort' />}
color={themes[theme].auxiliaryText}
onPress={toggleSort}
translateTitle={false}
/>
<List.Separator />
<OmnichannelStatus
searching={searching}
goQueue={goQueue}
inquiryEnabled={inquiryEnabled}
queueSize={queueSize}
user={user}
/>
</>
);
});
ListHeader.propTypes = {
searching: PropTypes.bool,
@ -33,7 +77,8 @@ ListHeader.propTypes = {
queueSize: PropTypes.number,
inquiryEnabled: PropTypes.bool,
encryptionBanner: PropTypes.string,
user: PropTypes.object
user: PropTypes.object,
theme: PropTypes.string
};
export default ListHeader;
export default withTheme(ListHeader);

View File

@ -1,46 +0,0 @@
import React from 'react';
import { View, Text, Image } from 'react-native';
import PropTypes from 'prop-types';
import styles from '../styles';
import Touch from '../../../utils/touch';
import I18n from '../../../i18n';
import { CustomIcon } from '../../../lib/Icons';
import Check from '../../../containers/Check';
import { themes } from '../../../constants/colors';
export const SortItemButton = ({ children, onPress, theme }) => (
<Touch
style={styles.sortItemButton}
onPress={onPress}
theme={theme}
>
{children}
</Touch>
);
SortItemButton.propTypes = {
theme: PropTypes.string,
children: PropTypes.node,
onPress: PropTypes.func
};
export const SortItemContent = ({
label, icon, imageUri, checked, theme
}) => (
<View style={styles.sortItemContainer}>
{icon && <CustomIcon style={[styles.sortIcon, { color: themes[theme].controlText }]} size={22} name={icon} />}
{imageUri && <Image style={[styles.sortIcon, { tintColor: themes[theme].controlText }]} source={{ uri: imageUri }} />}
<Text style={[styles.sortItemText, { color: themes[theme].controlText }]}>{I18n.t(label)}</Text>
{checked ? <Check theme={theme} /> : null}
</View>
);
SortItemContent.propTypes = {
theme: PropTypes.string,
label: PropTypes.string,
icon: PropTypes.string,
imageUri: PropTypes.string,
checked: PropTypes.bool
};

View File

@ -1,21 +1,19 @@
import React, { PureComponent } from 'react';
import {
View, Text, Animated, Easing, TouchableWithoutFeedback
Animated, Easing, TouchableWithoutFeedback
} from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withSafeAreaInsets } from 'react-native-safe-area-context';
import styles from '../styles';
import Touch from '../../../utils/touch';
import * as List from '../../../containers/List';
import RocketChat from '../../../lib/rocketchat';
import { setPreference } from '../../../actions/sortPreferences';
import log, { logEvent, events } from '../../../utils/log';
import I18n from '../../../i18n';
import { CustomIcon } from '../../../lib/Icons';
import { withTheme } from '../../../theme';
import { themes } from '../../../constants/colors';
import { SortItemButton, SortItemContent } from './Item';
import { headerHeight } from '../../../containers/Header';
const ANIMATION_DURATION = 200;
@ -113,6 +111,11 @@ class Sort extends PureComponent {
).start(() => close());
}
renderCheck = () => {
const { theme } = this.props;
return <List.Icon name='check' color={themes[theme].tintColor} />;
}
render() {
const { isMasterDetail, insets } = this.props;
const statusBarHeight = insets?.top ?? 0;
@ -150,58 +153,50 @@ class Sort extends PureComponent {
}
]}
>
<Touch
<List.Item
title={I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}
left={() => <List.Icon name='sort' />}
color={themes[theme].auxiliaryText}
onPress={this.close}
theme={theme}
>
<View style={[styles.dropdownContainerHeader, { borderColor: themes[theme].separatorColor }]}>
<View style={styles.sortItemContainer}>
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort' />
<Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
</View>
</View>
</Touch>
<SortItemButton onPress={this.sortByName} theme={theme}>
<SortItemContent
icon='sort-az'
label='Alphabetical'
checked={sortBy === 'alphabetical'}
theme={theme}
translateTitle={false}
/>
</SortItemButton>
<SortItemButton onPress={this.sortByActivity} theme={theme}>
<SortItemContent
icon='clock'
label='Activity'
checked={sortBy === 'activity'}
theme={theme}
<List.Separator />
<List.Item
title='Alphabetical'
left={() => <List.Icon name='sort-az' />}
color={themes[theme].auxiliaryText}
onPress={this.sortByName}
right={() => (sortBy === 'alphabetical' ? this.renderCheck() : null)}
/>
</SortItemButton>
<View style={[styles.sortSeparator, { backgroundColor: themes[theme].separatorColor }]} />
<SortItemButton onPress={this.toggleGroupByType} theme={theme}>
<SortItemContent
icon='group-by-type'
label='Group_by_type'
checked={groupByType}
theme={theme}
<List.Item
title='Activity'
left={() => <List.Icon name='clock' />}
color={themes[theme].auxiliaryText}
onPress={this.sortByActivity}
right={() => (sortBy === 'activity' ? this.renderCheck() : null)}
/>
</SortItemButton>
<SortItemButton onPress={this.toggleGroupByFavorites} theme={theme}>
<SortItemContent
icon='star'
label='Group_by_favorites'
checked={showFavorites}
theme={theme}
<List.Separator />
<List.Item
title='Group_by_type'
left={() => <List.Icon name='group-by-type' />}
color={themes[theme].auxiliaryText}
onPress={this.toggleGroupByType}
right={() => (groupByType ? this.renderCheck() : null)}
/>
</SortItemButton>
<SortItemButton onPress={this.toggleUnread} theme={theme}>
<SortItemContent
icon='unread-on-top-disabled'
label='Unread_on_top'
checked={showUnread}
theme={theme}
<List.Item
title='Group_by_favorites'
left={() => <List.Icon name='star' />}
color={themes[theme].auxiliaryText}
onPress={this.toggleGroupByFavorites}
right={() => (showFavorites ? this.renderCheck() : null)}
/>
<List.Item
title='Unread_on_top'
left={() => <List.Icon name='unread-on-top-disabled' />}
color={themes[theme].auxiliaryText}
onPress={this.toggleUnread}
right={() => (showUnread ? this.renderCheck() : null)}
/>
</SortItemButton>
</Animated.View>
</>
);

View File

@ -15,56 +15,22 @@ export default StyleSheet.create({
alignItems: 'center',
flexDirection: 'row'
},
sortToggleContainerClose: {
position: 'absolute',
top: 0,
width: '100%'
},
sortToggleText: {
fontSize: 16,
flex: 1,
...sharedStyles.textRegular
},
queueToggleText: {
fontSize: 16,
flex: 1,
...sharedStyles.textRegular
},
dropdownContainer: {
width: '100%',
position: 'absolute',
top: 0,
borderBottomWidth: StyleSheet.hairlineWidth
},
sortItemButton: {
height: 57,
justifyContent: 'center'
},
sortItemContainer: {
flexDirection: 'row',
alignItems: 'center'
},
sortItemText: {
fontSize: 18,
flex: 1,
...sharedStyles.textRegular
},
backdrop: {
...StyleSheet.absoluteFill
},
sortSeparator: {
height: StyleSheet.hairlineWidth,
marginHorizontal: 12,
flex: 1
},
sortIcon: {
width: 22,
height: 22,
marginHorizontal: 12
},
queueIcon: {
marginHorizontal: 12
},
omnichannelRightContainer: {
flexDirection: 'row',
alignItems: 'center'
},
groupTitleContainer: {
paddingHorizontal: 12,
paddingTop: 17,
@ -90,56 +56,5 @@ export default StyleSheet.create({
marginRight: 12,
paddingVertical: 10,
...sharedStyles.textRegular
},
serverItem: {
height: 68
},
serverItemContainer: {
flexDirection: 'row',
alignItems: 'center',
height: 68
},
serverIcon: {
width: 42,
height: 42,
marginHorizontal: 12,
marginVertical: 13,
borderRadius: 4,
resizeMode: 'contain'
},
serverTextContainer: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
},
serverName: {
fontSize: 18,
...sharedStyles.textSemibold
},
serverUrl: {
fontSize: 16,
...sharedStyles.textRegular
},
serverSeparator: {
height: StyleSheet.hairlineWidth,
marginLeft: 72
},
encryptionButton: {
width: '100%',
flexDirection: 'row',
alignItems: 'center',
padding: 12
},
encryptionIcon: {
...sharedStyles.textMedium
},
encryptionText: {
flex: 1,
fontSize: 16,
marginHorizontal: 16,
...sharedStyles.textMedium
},
omnichannelToggle: {
marginRight: 12
}
});

View File

@ -111,11 +111,20 @@ stories.add('with icon', () => (
</List.Container>
));
stories.add('with custom color', () => (
stories.add('with custom colors', () => (
<List.Container>
<List.Separator />
<List.Item title='Chats' color='red' />
<List.Separator />
<List.Item
title='Press me!'
color='white'
onPress={() => alert('Press')}
backgroundColor='red'
underlayColor='green'
translateTitle={false}
/>
<List.Separator />
</List.Container>
));