[IMPROVEMENT] List Component (#2506)
* List.Item * section * Start removing theme as prop * Remove StatusBar theme prop * SafeAreaView theme prop * Minor fixes * List.Container * Add translateTitle and translateSubtitle props * Storybook * Show action indicator * Header * Info * Theme stories * FlatList * DisplayName * Fix settings * FlatList tweaks * ThemeView * Screen Lock Config * DefaultBrowserView * PickerView and User Prefs * Notification Prefs * StatusView * Auto Translate * InviteUsersEdit * Visitor * Minor fixes * Remove Separator * Remove iteminfo * Font scale * Legal * Jitsi and e2e * Block * search, star, etc * auto translate and notifications * RoomInfo * Refactor RoomActions * lint * Remove DisclosureIndicator * padding horizontal 12 * Detox * Tests * Address review comments * Fix vertical scroll Co-authored-by: Djorkaeff Alexandre <djorkaeff.unb@gmail.com>
This commit is contained in:
parent
46e3db97e8
commit
52850cbccc
|
@ -1,4 +1,4 @@
|
|||
export default {
|
||||
activateKeepAwake: () => '',
|
||||
deactivateKeepAwake: () => ''
|
||||
};
|
||||
const activateKeepAwake = () => '';
|
||||
const deactivateKeepAwake = () => '';
|
||||
|
||||
export { activateKeepAwake, deactivateKeepAwake };
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,7 +27,7 @@ import { Button } from './Button';
|
|||
import { themes } from '../../constants/colors';
|
||||
import styles, { ITEM_HEIGHT } from './styles';
|
||||
import { isTablet, isIOS } from '../../utils/deviceInfo';
|
||||
import Separator from '../Separator';
|
||||
import * as List from '../List';
|
||||
import I18n from '../../i18n';
|
||||
import { useOrientation, useDimensions } from '../../dimensions';
|
||||
|
||||
|
@ -142,8 +142,6 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }, ref) => {
|
|||
</Button>
|
||||
) : null));
|
||||
|
||||
const renderSeparator = useCallback(() => <Separator theme={theme} style={styles.separator} />);
|
||||
|
||||
const renderItem = useCallback(({ item }) => <Item item={item} hide={hide} theme={theme} />);
|
||||
|
||||
const animatedPosition = React.useRef(new Value(0));
|
||||
|
@ -191,8 +189,8 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }, ref) => {
|
|||
keyExtractor={item => item.title}
|
||||
style={{ backgroundColor: themes[theme].focusedBackground }}
|
||||
contentContainerStyle={styles.content}
|
||||
ItemSeparatorComponent={renderSeparator}
|
||||
ListHeaderComponent={renderSeparator}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
ListHeaderComponent={List.Separator}
|
||||
ListFooterComponent={renderFooter}
|
||||
getItemLayout={getItemLayout}
|
||||
removeClippedSubviews={isIOS}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { themes } from '../constants/colors';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
disclosureContainer: {
|
||||
marginLeft: 6,
|
||||
marginRight: 9,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
export const DisclosureImage = React.memo(({ theme }) => (
|
||||
<CustomIcon
|
||||
name='chevron-right'
|
||||
color={themes[theme].auxiliaryText}
|
||||
size={20}
|
||||
/>
|
||||
));
|
||||
DisclosureImage.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
const DisclosureIndicator = React.memo(({ theme }) => (
|
||||
<View style={styles.disclosureContainer}>
|
||||
<DisclosureImage theme={theme} />
|
||||
</View>
|
||||
));
|
||||
DisclosureIndicator.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default DisclosureIndicator;
|
|
@ -31,14 +31,14 @@ const FormContainer = ({
|
|||
contentContainerStyle={sharedStyles.container}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<ScrollView
|
||||
style={sharedStyles.container}
|
||||
contentContainerStyle={[sharedStyles.containerScrollView, styles.scrollView]}
|
||||
{...scrollPersistTaps}
|
||||
{...props}
|
||||
>
|
||||
<SafeAreaView testID={testID} theme={theme} style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<SafeAreaView testID={testID} style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
{children}
|
||||
<AppVersion theme={theme} />
|
||||
</SafeAreaView>
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import sharedStyles from '../views/Styles';
|
||||
import { themes } from '../constants/colors';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
infoContainer: {
|
||||
padding: 15
|
||||
},
|
||||
infoText: {
|
||||
fontSize: 14,
|
||||
...sharedStyles.textRegular
|
||||
}
|
||||
});
|
||||
|
||||
const ItemInfo = React.memo(({ info, theme }) => (
|
||||
<View style={[styles.infoContainer, { backgroundColor: themes[theme].auxiliaryBackground }]}>
|
||||
<Text style={[styles.infoText, { color: themes[theme].infoText }]}>{info}</Text>
|
||||
</View>
|
||||
));
|
||||
|
||||
ItemInfo.propTypes = {
|
||||
info: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default ItemInfo;
|
|
@ -0,0 +1,30 @@
|
|||
import React from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTheme } from '../../theme';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
paddingVertical: 16
|
||||
}
|
||||
});
|
||||
|
||||
const ListContainer = React.memo(({ children, ...props }) => (
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.container}
|
||||
scrollIndicatorInsets={{ right: 1 }} // https://github.com/facebook/react-native/issues/26610#issuecomment-539843444
|
||||
{...scrollPersistTaps}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</ScrollView>
|
||||
));
|
||||
|
||||
ListContainer.propTypes = {
|
||||
children: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
ListContainer.displayName = 'List.Container';
|
||||
|
||||
export default withTheme(ListContainer);
|
|
@ -0,0 +1,40 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import I18n from '../../i18n';
|
||||
import { withTheme } from '../../theme';
|
||||
import { PADDING_HORIZONTAL } from './constants';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
paddingBottom: 12,
|
||||
paddingHorizontal: PADDING_HORIZONTAL
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
...sharedStyles.textRegular
|
||||
}
|
||||
});
|
||||
|
||||
const ListHeader = React.memo(({ title, theme, translateTitle }) => (
|
||||
<View style={styles.container}>
|
||||
<Text style={[styles.title, { color: themes[theme].infoText }]} numberOfLines={1}>{translateTitle ? I18n.t(title) : title}</Text>
|
||||
</View>
|
||||
));
|
||||
|
||||
ListHeader.propTypes = {
|
||||
title: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
translateTitle: PropTypes.bool
|
||||
};
|
||||
|
||||
ListHeader.defaultProps = {
|
||||
translateTitle: true
|
||||
};
|
||||
|
||||
ListHeader.displayName = 'List.Header';
|
||||
|
||||
export default withTheme(ListHeader);
|
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { themes } from '../../constants/colors';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import { withTheme } from '../../theme';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
icon: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
const ListIcon = React.memo(({ theme, name, color }) => (
|
||||
<View style={styles.icon}>
|
||||
<CustomIcon
|
||||
name={name}
|
||||
color={color ?? themes[theme].auxiliaryText}
|
||||
size={20}
|
||||
/>
|
||||
</View>
|
||||
));
|
||||
|
||||
ListIcon.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
color: PropTypes.string
|
||||
};
|
||||
|
||||
ListIcon.displayName = 'List.Icon';
|
||||
|
||||
export default withTheme(ListIcon);
|
|
@ -0,0 +1,40 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import { PADDING_HORIZONTAL } from './constants';
|
||||
import I18n from '../../i18n';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
paddingTop: 8,
|
||||
paddingHorizontal: PADDING_HORIZONTAL
|
||||
},
|
||||
text: {
|
||||
fontSize: 14,
|
||||
...sharedStyles.textRegular
|
||||
}
|
||||
});
|
||||
|
||||
const ListInfo = React.memo(({ info, translateInfo, theme }) => (
|
||||
<View style={styles.container}>
|
||||
<Text style={[styles.text, { color: themes[theme].infoText }]}>{translateInfo ? I18n.t(info) : info}</Text>
|
||||
</View>
|
||||
));
|
||||
|
||||
ListInfo.propTypes = {
|
||||
info: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
translateInfo: PropTypes.bool
|
||||
};
|
||||
|
||||
ListInfo.defaultProps = {
|
||||
translateInfo: true
|
||||
};
|
||||
|
||||
ListInfo.displayName = 'List.Info';
|
||||
|
||||
export default withTheme(ListInfo);
|
|
@ -0,0 +1,137 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Touch from '../../utils/touch';
|
||||
import { themes } from '../../constants/colors';
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { withTheme } from '../../theme';
|
||||
import I18n from '../../i18n';
|
||||
import { Icon } from '.';
|
||||
import { BASE_HEIGHT, PADDING_HORIZONTAL } from './constants';
|
||||
import { withDimensions } from '../../dimensions';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: PADDING_HORIZONTAL
|
||||
},
|
||||
leftContainer: {
|
||||
paddingRight: PADDING_HORIZONTAL
|
||||
},
|
||||
rightContainer: {
|
||||
paddingLeft: PADDING_HORIZONTAL
|
||||
},
|
||||
disabled: {
|
||||
opacity: 0.3
|
||||
},
|
||||
textContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center'
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
...sharedStyles.textRegular
|
||||
}
|
||||
});
|
||||
|
||||
const Content = React.memo(({
|
||||
title, subtitle, disabled, testID, left, right, color, theme, translateTitle, translateSubtitle, showActionIndicator, fontScale
|
||||
}) => (
|
||||
<View style={[styles.container, disabled && styles.disabled, { height: BASE_HEIGHT * fontScale }]} testID={testID}>
|
||||
{left
|
||||
? (
|
||||
<View style={styles.leftContainer}>
|
||||
{left()}
|
||||
</View>
|
||||
)
|
||||
: null}
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={[styles.title, { color: color || themes[theme].titleText }]} numberOfLines={1}>{translateTitle ? I18n.t(title) : title}</Text>
|
||||
{subtitle
|
||||
? <Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>{translateSubtitle ? I18n.t(subtitle) : subtitle}</Text>
|
||||
: null
|
||||
}
|
||||
</View>
|
||||
{right || showActionIndicator
|
||||
? (
|
||||
<View style={styles.rightContainer}>
|
||||
{right ? right() : null}
|
||||
{showActionIndicator ? <Icon name='chevron-right' /> : null}
|
||||
</View>
|
||||
)
|
||||
: null}
|
||||
</View>
|
||||
));
|
||||
|
||||
const Button = React.memo(({
|
||||
onPress, ...props
|
||||
}) => (
|
||||
<Touch
|
||||
onPress={() => onPress(props.title)}
|
||||
style={{ backgroundColor: themes[props.theme].backgroundColor }}
|
||||
enabled={!props.disabled}
|
||||
theme={props.theme}
|
||||
>
|
||||
<Content {...props} />
|
||||
</Touch>
|
||||
));
|
||||
|
||||
const ListItem = React.memo(({ ...props }) => {
|
||||
if (props.onPress) {
|
||||
return <Button {...props} />;
|
||||
}
|
||||
return (
|
||||
<View style={{ backgroundColor: themes[props.theme].backgroundColor }}>
|
||||
<Content {...props} />
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
ListItem.propTypes = {
|
||||
onPress: PropTypes.func,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
ListItem.displayName = 'List.Item';
|
||||
|
||||
Content.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
subtitle: PropTypes.string,
|
||||
left: PropTypes.func,
|
||||
right: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
testID: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
color: PropTypes.string,
|
||||
translateTitle: PropTypes.bool,
|
||||
translateSubtitle: PropTypes.bool,
|
||||
showActionIndicator: PropTypes.bool,
|
||||
fontScale: PropTypes.number
|
||||
};
|
||||
|
||||
Content.defaultProps = {
|
||||
translateTitle: true,
|
||||
translateSubtitle: true,
|
||||
showActionIndicator: false
|
||||
};
|
||||
|
||||
Button.propTypes = {
|
||||
title: PropTypes.string,
|
||||
onPress: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
disabled: false
|
||||
};
|
||||
|
||||
export default withTheme(withDimensions(ListItem));
|
|
@ -0,0 +1,28 @@
|
|||
import React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTheme } from '../../theme';
|
||||
import { Header } from '.';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginVertical: 16
|
||||
}
|
||||
});
|
||||
|
||||
const ListSection = React.memo(({ children, title, translateTitle }) => (
|
||||
<View style={styles.container}>
|
||||
{title ? <Header {...{ title, translateTitle }} /> : null}
|
||||
{children}
|
||||
</View>
|
||||
));
|
||||
|
||||
ListSection.propTypes = {
|
||||
children: PropTypes.array.isRequired,
|
||||
title: PropTypes.string,
|
||||
translateTitle: PropTypes.bool
|
||||
};
|
||||
|
||||
ListSection.displayName = 'List.Section';
|
||||
|
||||
export default withTheme(ListSection);
|
|
@ -2,7 +2,8 @@ import React from 'react';
|
|||
import { View, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { themes } from '../constants/colors';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
separator: {
|
||||
|
@ -11,7 +12,7 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
|
||||
const Separator = React.memo(({ style, theme }) => (
|
||||
const ListSeparator = React.memo(({ style, theme }) => (
|
||||
<View
|
||||
style={[
|
||||
styles.separator,
|
||||
|
@ -21,9 +22,11 @@ const Separator = React.memo(({ style, theme }) => (
|
|||
/>
|
||||
));
|
||||
|
||||
Separator.propTypes = {
|
||||
ListSeparator.propTypes = {
|
||||
style: PropTypes.object,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default Separator;
|
||||
ListSeparator.displayName = 'List.Separator';
|
||||
|
||||
export default withTheme(ListSeparator);
|
|
@ -0,0 +1,2 @@
|
|||
export const PADDING_HORIZONTAL = 12;
|
||||
export const BASE_HEIGHT = 46;
|
|
@ -0,0 +1,8 @@
|
|||
export { default as Container } from './ListContainer';
|
||||
export { default as Item } from './ListItem';
|
||||
export { default as Section } from './ListSection';
|
||||
export { default as Icon } from './ListIcon';
|
||||
export { default as Separator } from './ListSeparator';
|
||||
export { default as Header } from './ListHeader';
|
||||
export { default as Info } from './ListInfo';
|
||||
export * from './styles';
|
|
@ -0,0 +1,7 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
contentContainerStyleFlatList: {
|
||||
paddingVertical: 32
|
||||
}
|
||||
});
|
|
@ -1,102 +0,0 @@
|
|||
import React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Touch from '../utils/touch';
|
||||
import { themes } from '../constants/colors';
|
||||
import sharedStyles from '../views/Styles';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: 46,
|
||||
paddingHorizontal: 15
|
||||
},
|
||||
disabled: {
|
||||
opacity: 0.3
|
||||
},
|
||||
textContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center'
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
...sharedStyles.textRegular
|
||||
}
|
||||
});
|
||||
|
||||
const Content = React.memo(({
|
||||
title, subtitle, disabled, testID, left, right, color, theme
|
||||
}) => (
|
||||
<View style={[styles.container, disabled && styles.disabled]} testID={testID}>
|
||||
{left ? left() : null}
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={[styles.title, { color: color || themes[theme].titleText }]}>{title}</Text>
|
||||
{subtitle
|
||||
? <Text style={[styles.subtitle, { color: themes[theme].bodyText }]}>{subtitle}</Text>
|
||||
: null
|
||||
}
|
||||
</View>
|
||||
{right ? right() : null}
|
||||
</View>
|
||||
));
|
||||
|
||||
const Button = React.memo(({
|
||||
onPress, ...props
|
||||
}) => (
|
||||
<Touch
|
||||
onPress={() => onPress(props.title)}
|
||||
style={{ backgroundColor: themes[props.theme].backgroundColor }}
|
||||
enabled={!props.disabled}
|
||||
theme={props.theme}
|
||||
>
|
||||
<Content {...props} />
|
||||
</Touch>
|
||||
));
|
||||
|
||||
const Item = React.memo(({ ...props }) => {
|
||||
if (props.onPress) {
|
||||
return <Button {...props} />;
|
||||
}
|
||||
return (
|
||||
<View style={{ backgroundColor: themes[props.theme].backgroundColor }}>
|
||||
<Content {...props} />
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
Item.propTypes = {
|
||||
onPress: PropTypes.func,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
Content.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
subtitle: PropTypes.string,
|
||||
left: PropTypes.func,
|
||||
right: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
testID: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
color: PropTypes.string
|
||||
};
|
||||
|
||||
Button.propTypes = {
|
||||
title: PropTypes.string,
|
||||
onPress: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
disabled: false
|
||||
};
|
||||
|
||||
export default Item;
|
|
@ -99,7 +99,7 @@ const ModalContent = React.memo(({
|
|||
}) => {
|
||||
if (message && message.reactions) {
|
||||
return (
|
||||
<SafeAreaView theme={props.theme} style={styles.safeArea}>
|
||||
<SafeAreaView style={styles.safeArea}>
|
||||
<Touchable onPress={onClose}>
|
||||
<View style={styles.titleContainer}>
|
||||
<CustomIcon
|
||||
|
|
|
@ -3,6 +3,7 @@ import { StyleSheet } from 'react-native';
|
|||
import PropTypes from 'prop-types';
|
||||
import { SafeAreaView as SafeAreaContext } from 'react-native-safe-area-context';
|
||||
import { themes } from '../constants/colors';
|
||||
import { withTheme } from '../theme';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
view: {
|
||||
|
@ -31,4 +32,4 @@ SafeAreaView.propTypes = {
|
|||
children: PropTypes.element
|
||||
};
|
||||
|
||||
export default SafeAreaView;
|
||||
export default withTheme(SafeAreaView);
|
||||
|
|
|
@ -3,6 +3,7 @@ import { StatusBar as StatusBarRN } from 'react-native';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import { themes } from '../constants/colors';
|
||||
import { withTheme } from '../theme';
|
||||
|
||||
const StatusBar = React.memo(({ theme, barStyle, backgroundColor }) => {
|
||||
if (!barStyle) {
|
||||
|
@ -20,4 +21,4 @@ StatusBar.propTypes = {
|
|||
backgroundColor: PropTypes.string
|
||||
};
|
||||
|
||||
export default StatusBar;
|
||||
export default withTheme(StatusBar);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Separator from '../Separator';
|
||||
import * as List from '../List';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
separator: {
|
||||
|
@ -12,7 +11,4 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
export const Divider = ({ theme }) => <Separator style={styles.separator} theme={theme} />;
|
||||
Divider.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
export const Divider = () => <List.Separator style={styles.separator} />;
|
||||
|
|
|
@ -4,9 +4,8 @@ import PropTypes from 'prop-types';
|
|||
import Touchable from 'react-native-platform-touchable';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import Separator from '../../Separator';
|
||||
import Check from '../../Check';
|
||||
|
||||
import * as List from '../../List';
|
||||
import { textParser } from '../utils';
|
||||
import { themes } from '../../../constants/colors';
|
||||
|
||||
|
@ -48,7 +47,7 @@ const Items = ({
|
|||
style={[styles.items, { backgroundColor: themes[theme].backgroundColor }]}
|
||||
contentContainerStyle={[styles.itemContent, { backgroundColor: themes[theme].backgroundColor }]}
|
||||
keyboardShouldPersistTaps='always'
|
||||
ItemSeparatorComponent={() => <Separator theme={theme} />}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
keyExtractor={keyExtractor}
|
||||
renderItem={({ item }) => <Item item={item} onSelect={onSelect} theme={theme} selected={selected.find(s => s === item.value)} />}
|
||||
/>
|
||||
|
|
|
@ -5,10 +5,10 @@ import Popover from 'react-native-popover-view';
|
|||
import Touchable from 'react-native-platform-touchable';
|
||||
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import Separator from '../Separator';
|
||||
import ActivityIndicator from '../ActivityIndicator';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { BUTTON_HIT_SLOP } from '../message/utils';
|
||||
import * as List from '../List';
|
||||
|
||||
const keyExtractor = item => item.value;
|
||||
|
||||
|
@ -50,7 +50,7 @@ const Options = ({
|
|||
data={options}
|
||||
renderItem={({ item }) => <Option option={item} onOptionPress={onOptionPress} parser={parser} theme={theme} />}
|
||||
keyExtractor={keyExtractor}
|
||||
ItemSeparatorComponent={() => <Separator theme={theme} />}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
/>
|
||||
);
|
||||
Options.propTypes = {
|
||||
|
|
|
@ -5,7 +5,6 @@ import PropTypes from 'prop-types';
|
|||
|
||||
import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import DisclosureIndicator from '../DisclosureIndicator';
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import I18n from '../../i18n';
|
||||
|
@ -33,7 +32,13 @@ const RepliedThread = React.memo(({
|
|||
<View style={styles.repliedThread} testID={`message-thread-replied-on-${ msg }`}>
|
||||
<CustomIcon name='threads' size={20} style={styles.repliedThreadIcon} color={themes[theme].tintColor} />
|
||||
<Text style={[styles.repliedThreadName, { color: themes[theme].tintColor }]} numberOfLines={1}>{msg}</Text>
|
||||
<DisclosureIndicator theme={theme} />
|
||||
<View style={styles.repliedThreadDisclosure}>
|
||||
<CustomIcon
|
||||
name='chevron-right'
|
||||
color={themes[theme].auxiliaryText}
|
||||
size={20}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}, (prevProps, nextProps) => {
|
||||
|
|
|
@ -164,6 +164,12 @@ export default StyleSheet.create({
|
|||
flex: 1,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
repliedThreadDisclosure: {
|
||||
marginLeft: 4,
|
||||
marginRight: 4,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
readReceipt: {
|
||||
lineHeight: 20
|
||||
},
|
||||
|
|
|
@ -128,8 +128,8 @@ class QueueListView extends React.Component {
|
|||
render() {
|
||||
const { queued, theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='queue-list-view' theme={theme} style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='queue-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar />
|
||||
<FlatList
|
||||
ref={this.getScrollRef}
|
||||
data={queued}
|
||||
|
|
|
@ -100,7 +100,6 @@ export default {
|
|||
announcement: 'Ankündigung',
|
||||
Announcement: 'Ankündigung',
|
||||
Apply_Your_Certificate: 'Wende dein Zertifikat an',
|
||||
Applying_a_theme_will_change_how_the_app_looks: 'Das Erscheinungsbild festzulegen wird das Aussehen der Anwendung ändern.',
|
||||
ARCHIVE: 'ARCHIV',
|
||||
archive: 'Archiv',
|
||||
are_typing: 'tippen',
|
||||
|
@ -180,7 +179,7 @@ export default {
|
|||
deleting_room: 'lösche Raum',
|
||||
description: 'Beschreibung',
|
||||
Description: 'Beschreibung',
|
||||
DESKTOP_OPTIONS: 'Desktop-Einstellungen',
|
||||
Desktop_Options: 'Desktop-Einstellungen',
|
||||
Directory: 'Verzeichnis',
|
||||
Direct_Messages: 'Direkte Nachrichten',
|
||||
Disable_notifications: 'Benachrichtigungen deaktiveren',
|
||||
|
@ -198,9 +197,8 @@ export default {
|
|||
Edit_Status: 'Status ändern',
|
||||
Edit_Invite: 'Einladung bearbeiten',
|
||||
Email_or_password_field_is_empty: 'Das E-Mail- oder Passwortfeld ist leer',
|
||||
Email: 'Email',
|
||||
EMAIL: 'EMAIL',
|
||||
email: 'Email',
|
||||
Email: 'E-mail',
|
||||
email: 'E-mail',
|
||||
Empty_title: 'leerer Titel',
|
||||
Enable_Auto_Translate: 'Automatische Übersetzung aktivieren',
|
||||
Enable_notifications: 'Benachrichtigungen aktivieren',
|
||||
|
@ -247,7 +245,7 @@ export default {
|
|||
Message_HideType_room_unarchived: 'Raum nicht mehr archiviert',
|
||||
IP: 'IP',
|
||||
In_app: 'In-App-Browser',
|
||||
IN_APP_AND_DESKTOP: 'IN-APP UND DESKTOP',
|
||||
In_App_And_Desktop: 'In-app und Desktop',
|
||||
In_App_and_Desktop_Alert_info: 'Zeigt ein Banner oben am Bildschirm, wenn die App geöffnet ist und eine Benachrichtigung auf dem Desktop.',
|
||||
Invisible: 'Unsichtbar',
|
||||
Invite: 'Einladen',
|
||||
|
@ -373,7 +371,7 @@ export default {
|
|||
Profile: 'Profil',
|
||||
Public_Channel: 'Öffentlicher Kanal',
|
||||
Public: 'Öffentlich',
|
||||
PUSH_NOTIFICATIONS: 'Push-Benachrichtigungen',
|
||||
Push_Notifications: 'Push-Benachrichtigungen',
|
||||
Push_Notifications_Alert_Info: 'Diese Benachrichtigungen werden Ihnen zugestellt, wenn die App nicht geöffnet ist.',
|
||||
Quote: 'Zitat',
|
||||
Reactions_are_disabled: 'Reaktionen sind deaktiviert',
|
||||
|
|
|
@ -100,7 +100,6 @@ export default {
|
|||
announcement: 'announcement',
|
||||
Announcement: 'Announcement',
|
||||
Apply_Your_Certificate: 'Apply Your Certificate',
|
||||
Applying_a_theme_will_change_how_the_app_looks: 'Applying a theme will change how the app looks.',
|
||||
ARCHIVE: 'ARCHIVE',
|
||||
archive: 'archive',
|
||||
are_typing: 'are typing',
|
||||
|
@ -184,8 +183,8 @@ export default {
|
|||
deleting_room: 'deleting room',
|
||||
description: 'description',
|
||||
Description: 'Description',
|
||||
DESKTOP_OPTIONS: 'DESKTOP OPTIONS',
|
||||
DESKTOP_NOTIFICATIONS: 'DESKTOP NOTIFICATIONS',
|
||||
Desktop_Options: 'Desktop Options',
|
||||
Desktop_Notifications: 'Desktop Notifications',
|
||||
Desktop_Alert_info: 'These notifications are delivered in desktop',
|
||||
Directory: 'Directory',
|
||||
Direct_Messages: 'Direct Messages',
|
||||
|
@ -212,8 +211,7 @@ export default {
|
|||
Email_Notification_Mode_All: 'Every Mention/DM',
|
||||
Email_Notification_Mode_Disabled: 'Disabled',
|
||||
Email_or_password_field_is_empty: 'Email or password field is empty',
|
||||
Email: 'Email',
|
||||
EMAIL: 'EMAIL',
|
||||
Email: 'E-mail',
|
||||
email: 'e-mail',
|
||||
Empty_title: 'Empty title',
|
||||
Enable_Auto_Translate: 'Enable Auto-Translate',
|
||||
|
@ -270,7 +268,7 @@ export default {
|
|||
I_Saved_My_E2E_Password: 'I Saved My E2E Password',
|
||||
IP: 'IP',
|
||||
In_app: 'In-app',
|
||||
IN_APP_AND_DESKTOP: 'IN-APP AND DESKTOP',
|
||||
In_App_And_Desktop: 'In-app and Desktop',
|
||||
In_App_and_Desktop_Alert_info: 'Displays a banner at the top of the screen when app is open, and displays a notification on desktop',
|
||||
Invisible: 'Invisible',
|
||||
Invite: 'Invite',
|
||||
|
@ -398,7 +396,7 @@ export default {
|
|||
Profile: 'Profile',
|
||||
Public_Channel: 'Public Channel',
|
||||
Public: 'Public',
|
||||
PUSH_NOTIFICATIONS: 'PUSH NOTIFICATIONS',
|
||||
Push_Notifications: 'Push Notifications',
|
||||
Push_Notifications_Alert_Info: 'These notifications are delivered to you when the app is not open',
|
||||
Quote: 'Quote',
|
||||
Reactions_are_disabled: 'Reactions are disabled',
|
||||
|
|
|
@ -95,7 +95,6 @@ export default {
|
|||
announcement: 'anuncio',
|
||||
Announcement: 'Anuncio',
|
||||
Apply_Your_Certificate: 'Applica tu Certificación',
|
||||
Applying_a_theme_will_change_how_the_app_looks: 'Aplicando un tema modificará el aspecto de la App.',
|
||||
ARCHIVE: 'FICHERO',
|
||||
archive: 'Fichero',
|
||||
are_typing: 'escribiendo',
|
||||
|
@ -160,7 +159,7 @@ export default {
|
|||
deleting_room: 'eliminando sala',
|
||||
description: 'descripción',
|
||||
Description: 'Descripción',
|
||||
DESKTOP_OPTIONS: 'OPCIONES DE ESCRITORIO',
|
||||
Desktop_Options: 'Opciones De Escritorio',
|
||||
Directory: 'Directorio',
|
||||
Direct_Messages: 'Mensajes directo',
|
||||
Disable_notifications: 'Desactivar notificaciones',
|
||||
|
@ -172,8 +171,7 @@ export default {
|
|||
edited: 'editado',
|
||||
Edit: 'Editar',
|
||||
Email_or_password_field_is_empty: 'El email o la contraseña están vacios',
|
||||
Email: 'Email',
|
||||
EMAIL: 'EMAIL',
|
||||
Email: 'E-mail',
|
||||
email: 'e-mail',
|
||||
Enable_Auto_Translate: 'Permitir Auto-Translate',
|
||||
Enable_notifications: 'Permitir notificaciones',
|
||||
|
@ -197,7 +195,7 @@ export default {
|
|||
Has_joined_the_channel: 'Se ha unido al canal',
|
||||
Has_joined_the_conversation: 'Se ha unido a la conversación',
|
||||
Has_left_the_channel: 'Ha dejado el canal',
|
||||
IN_APP_AND_DESKTOP: 'IN-APP AND DESKTOP',
|
||||
In_App_And_Desktop: 'In-app and Desktop',
|
||||
In_App_and_Desktop_Alert_info: 'Muestra un banner en la parte superior de la pantalla cuando la aplicación está abierta y muestra una notificación en el escritorio',
|
||||
Invisible: 'Invisible',
|
||||
Invite: 'Invitar',
|
||||
|
@ -290,7 +288,7 @@ export default {
|
|||
Profile: 'Perfil',
|
||||
Public_Channel: 'Canal público',
|
||||
Public: 'Público',
|
||||
PUSH_NOTIFICATIONS: 'PUSH NOTIFICATIONS',
|
||||
Push_Notifications: 'Push Notifications',
|
||||
Push_Notifications_Alert_Info: 'Estas notificaciones se le entregan cuando la aplicación no está abierta',
|
||||
Quote: 'Citar',
|
||||
Reactions_are_disabled: 'Las reacciones están desactivadas',
|
||||
|
|
|
@ -100,7 +100,6 @@ export default {
|
|||
announcement: 'annonce',
|
||||
Announcement: 'Annonce',
|
||||
Apply_Your_Certificate: 'Valider le Certificat',
|
||||
Applying_a_theme_will_change_how_the_app_looks: 'Valider un thème va modifier l\'affichage de l\'application.',
|
||||
ARCHIVE: 'ARCHIVER',
|
||||
archive: 'archiver',
|
||||
are_typing: 'sont en train d\'écrire',
|
||||
|
@ -180,7 +179,7 @@ export default {
|
|||
deleting_room: 'effacement de la salle',
|
||||
description: 'la description',
|
||||
Description: 'La description',
|
||||
DESKTOP_OPTIONS: 'DESKTOP OPTIONS',
|
||||
Desktop_Options: 'Desktop Options',
|
||||
Directory: 'Répertoire',
|
||||
Direct_Messages: 'Messages directs',
|
||||
Disable_notifications: 'Désactiver les notifications',
|
||||
|
@ -199,7 +198,6 @@ export default {
|
|||
Edit_Invite: 'Modifier l\'invitation',
|
||||
Email_or_password_field_is_empty: 'Le champ e-mail ou mot de passe est vide',
|
||||
Email: 'E-mail',
|
||||
EMAIL: 'EMAIL',
|
||||
email: 'e-mail',
|
||||
Empty_title: 'Titre vide',
|
||||
Enable_Auto_Translate: 'Activer la traduction-auto',
|
||||
|
@ -247,7 +245,7 @@ export default {
|
|||
Message_HideType_room_unarchived: 'Salon Désarchivé',
|
||||
IP: 'IP',
|
||||
In_app: 'In-app',
|
||||
IN_APP_AND_DESKTOP: 'IN-APP ET BUREAU',
|
||||
In_App_And_Desktop: 'In-app et Bureau',
|
||||
In_App_and_Desktop_Alert_info: 'Affiche une bannière en haut de l\'écran lorsque l\'application est ouverte et affiche une notification sur le bureau',
|
||||
Invisible: 'Invisible',
|
||||
Invite: 'Inviter',
|
||||
|
@ -373,7 +371,7 @@ export default {
|
|||
Profile: 'Profil',
|
||||
Public_Channel: 'Canal Public',
|
||||
Public: 'Public',
|
||||
PUSH_NOTIFICATIONS: 'NOTIFICATIONS PUSH',
|
||||
Push_Notifications: 'Notifications Push',
|
||||
Push_Notifications_Alert_Info: 'Ces notifications vous sont livrées lorsque l\'application n\'est pas ouverte',
|
||||
Quote: 'Citation',
|
||||
Reactions_are_disabled: 'Les réactions sont désactivées',
|
||||
|
|
|
@ -100,7 +100,6 @@ export default {
|
|||
announcement: 'annuncio',
|
||||
Announcement: 'Annuncio',
|
||||
Apply_Your_Certificate: 'Applica il tuo certificato',
|
||||
Applying_a_theme_will_change_how_the_app_looks: 'Applicare un tema cambierà l\'aspetto dell\'app.',
|
||||
ARCHIVE: 'ARCHIVIO',
|
||||
archive: 'archivio',
|
||||
are_typing: 'stanno scrivendo',
|
||||
|
@ -184,8 +183,8 @@ export default {
|
|||
deleting_room: 'cancellazione stanza',
|
||||
description: 'descrizione',
|
||||
Description: 'Descrizione',
|
||||
DESKTOP_OPTIONS: 'OPZIONI DESKTOP',
|
||||
DESKTOP_NOTIFICATIONS: 'NOTIFICHE DESKTOP',
|
||||
Desktop_Options: 'Opzioni Desktop',
|
||||
Desktop_Notifications: 'Notifiche Desktop',
|
||||
Desktop_Alert_info: 'Queste notifiche vengono inviate sul client desktop',
|
||||
Directory: 'Rubrica',
|
||||
Direct_Messages: 'Messaggi diretti',
|
||||
|
@ -213,7 +212,6 @@ export default {
|
|||
Email_Notification_Mode_Disabled: 'Disabilitato',
|
||||
Email_or_password_field_is_empty: 'Il campo e-mail o password sono vuoti',
|
||||
Email: 'E-mail',
|
||||
EMAIL: 'E-MAIL',
|
||||
email: 'e-mail',
|
||||
Empty_title: 'Titolo vuoto',
|
||||
Enable_Auto_Translate: 'Abilita traduzione automatica',
|
||||
|
@ -270,7 +268,7 @@ export default {
|
|||
I_Saved_My_E2E_Password: 'Ho salvato la mia Password E2E',
|
||||
IP: 'Indirizzo IP',
|
||||
In_app: 'In-app',
|
||||
IN_APP_AND_DESKTOP: 'IN-APP E DESKTOP',
|
||||
In_App_And_Desktop: 'In-app e Desktop',
|
||||
In_App_and_Desktop_Alert_info: 'Mostra una notifica in cima allo schermo quando l\'app è aperta, e mostra una notifica sul desktop',
|
||||
Invisible: 'Invisibile',
|
||||
Invite: 'Invita',
|
||||
|
@ -398,7 +396,7 @@ export default {
|
|||
Profile: 'Profilo',
|
||||
Public_Channel: 'Canale pubblico',
|
||||
Public: 'Pubblico',
|
||||
PUSH_NOTIFICATIONS: 'NOTIFICHE PUSH',
|
||||
Push_Notifications: 'Notifiche Push',
|
||||
Push_Notifications_Alert_Info: 'Queste notifiche ti vengono recapitate quando l\'app non è aperta',
|
||||
Quote: 'Cita',
|
||||
Reactions_are_disabled: 'Le reazioni sono disabilitate',
|
||||
|
|
|
@ -110,8 +110,6 @@ export default {
|
|||
announcement: 'アナウンス',
|
||||
Announcement: 'アナウンス',
|
||||
Apply_Your_Certificate: '証明書を適用する',
|
||||
Applying_a_theme_will_change_how_the_app_looks:
|
||||
'テーマを変更すると見た目が変わります',
|
||||
ARCHIVE: 'アーカイブ',
|
||||
archive: 'アーカイブ',
|
||||
are_typing: 'が入力中',
|
||||
|
@ -183,7 +181,7 @@ export default {
|
|||
deleting_room: 'ルームを削除',
|
||||
description: '概要',
|
||||
Description: '概要',
|
||||
DESKTOP_OPTIONS: 'デスクトップオプション',
|
||||
Desktop_Options: 'デスクトップオプション',
|
||||
Directory: 'ディレクトリ',
|
||||
Direct_Messages: 'ダイレクトメッセージ',
|
||||
Disable_notifications: '通知を無効化',
|
||||
|
@ -198,7 +196,6 @@ export default {
|
|||
Edit_Invite: '編集に招待',
|
||||
Email_or_password_field_is_empty: 'メールアドレスかパスワードの入力欄が空です',
|
||||
Email: 'メールアドレス',
|
||||
EMAIL: 'メールアドレス',
|
||||
email: 'メールアドレス',
|
||||
Enable_Auto_Translate: '自動翻訳を有効にする',
|
||||
Enable_markdown: 'マークダウンを有効にする',
|
||||
|
@ -227,7 +224,7 @@ export default {
|
|||
Has_joined_the_channel: 'はチャンネルに参加しました',
|
||||
Has_joined_the_conversation: 'は会話に参加しました',
|
||||
Has_left_the_channel: 'はチャンネルを退出しました',
|
||||
IN_APP_AND_DESKTOP: 'アプリ内とデスクトップ',
|
||||
In_App_And_Desktop: 'アプリ内とデスクトップ',
|
||||
In_App_and_Desktop_Alert_info:
|
||||
'アプリを表示中にはバナーを上部に表示し、デスクトップには通知を送ります。',
|
||||
Invisible: '状態を隠す',
|
||||
|
@ -332,7 +329,7 @@ export default {
|
|||
Profile: 'プロフィール',
|
||||
Public_Channel: 'パブリックチャンネル',
|
||||
Public: 'パブリック',
|
||||
PUSH_NOTIFICATIONS: 'プッシュ通知',
|
||||
Push_Notifications: 'プッシュ通知',
|
||||
Push_Notifications_Alert_Info:
|
||||
'通知はアプリを開いていない時に送られます。',
|
||||
Quote: '引用',
|
||||
|
|
|
@ -96,7 +96,6 @@ export default {
|
|||
announcement: 'aankondiging',
|
||||
Announcement: 'Aankondiging',
|
||||
Apply_Your_Certificate: 'Gebruik je certificaat',
|
||||
Applying_a_theme_will_change_how_the_app_looks: 'Een thema toepassen verandert de looks van de app.',
|
||||
ARCHIVE: 'ARCHIVEER',
|
||||
archive: 'archiveer',
|
||||
are_typing: 'zijn aan het typen',
|
||||
|
@ -162,7 +161,7 @@ export default {
|
|||
deleting_room: 'kamer legen',
|
||||
description: 'beschrijving',
|
||||
Description: 'Beschrijving',
|
||||
DESKTOP_OPTIONS: 'DESKTOP OPTIES',
|
||||
Desktop_Options: 'Desktop Opties',
|
||||
Directory: 'Map',
|
||||
Direct_Messages: 'Directe berichten',
|
||||
Disable_notifications: 'Zet notificaties uit',
|
||||
|
@ -175,8 +174,7 @@ export default {
|
|||
Edit: 'Bewerk',
|
||||
Edit_Invite: 'Bewerk uitnodiging',
|
||||
Email_or_password_field_is_empty: 'Email of wachtwoord veld is leeg',
|
||||
Email: 'Email',
|
||||
EMAIL: 'EMAIL',
|
||||
Email: 'E-mail',
|
||||
email: 'e-mail',
|
||||
Enable_Auto_Translate: 'Zet Auto-Translate aan',
|
||||
Enable_notifications: 'Zet notifications aan',
|
||||
|
@ -202,7 +200,7 @@ export default {
|
|||
Has_joined_the_channel: 'Is bij het kanaal gekomen',
|
||||
Has_joined_the_conversation: 'Neemt deel aan het gesprek',
|
||||
Has_left_the_channel: 'Heeft het kanaal verlaten',
|
||||
IN_APP_AND_DESKTOP: 'IN-APP EN DESKTOP',
|
||||
In_App_And_Desktop: 'In-app en Desktop',
|
||||
In_App_and_Desktop_Alert_info: 'Laat een banner bovenaan het scherm zien als de app open is en geeft een notificatie op de desktop',
|
||||
Invisible: 'Onzichtbaar',
|
||||
Invite: 'Nodig uit',
|
||||
|
@ -301,7 +299,7 @@ export default {
|
|||
Profile: 'Profiel',
|
||||
Public_Channel: 'Publiek kanaal',
|
||||
Public: 'Publiek',
|
||||
PUSH_NOTIFICATIONS: 'PUSHNOTIFICATIES',
|
||||
Push_Notifications: 'Pushnotificaties',
|
||||
Push_Notifications_Alert_Info: 'Deze notificaties krijg je als de app niet geopend is',
|
||||
Quote: 'Quote',
|
||||
Reactions_are_disabled: 'Reacties zijn uitgeschakeld',
|
||||
|
|
|
@ -102,7 +102,6 @@ export default {
|
|||
and: 'e',
|
||||
announcement: 'anúncio',
|
||||
Announcement: 'Anúncio',
|
||||
Applying_a_theme_will_change_how_the_app_looks: 'Aplicar um tema mudará a aparência do app.',
|
||||
ARCHIVE: 'ARQUIVAR',
|
||||
archive: 'arquivar',
|
||||
are_typing: 'estão digitando',
|
||||
|
@ -178,8 +177,8 @@ export default {
|
|||
DELETE: 'EXCLUIR',
|
||||
deleting_room: 'excluindo sala',
|
||||
Direct_Messages: 'Mensagens Diretas',
|
||||
DESKTOP_OPTIONS: 'OPÇÕES DE ÁREA DE TRABALHO',
|
||||
DESKTOP_NOTIFICATIONS: 'NOTIFICAÇÕES DE ÁREA DE TRABALHO',
|
||||
Desktop_Options: 'Opções De Área De Trabalho',
|
||||
Desktop_Notifications: 'Notificações da Área de Trabalho',
|
||||
Desktop_Alert_info: 'Essas notificações são entregues a você na área de trabalho',
|
||||
Directory: 'Diretório',
|
||||
description: 'descrição',
|
||||
|
@ -204,7 +203,7 @@ export default {
|
|||
End_to_end_encrypted_room: 'Sala criptografada de ponta a ponta',
|
||||
end_to_end_encryption: 'criptografia de ponta a ponta',
|
||||
Email_or_password_field_is_empty: 'Email ou senha estão vazios',
|
||||
Email: 'Email',
|
||||
Email: 'E-mail',
|
||||
email: 'e-mail',
|
||||
Empty_title: 'Título vazio',
|
||||
Email_Notification_Mode_All: 'Cada Menção / Mensagem Direta',
|
||||
|
@ -372,6 +371,7 @@ export default {
|
|||
Profile: 'Perfil',
|
||||
Public_Channel: 'Canal Público',
|
||||
Public: 'Público',
|
||||
Push_Notifications: 'Notificações Push',
|
||||
Push_Notifications_Alert_Info: 'Essas notificações são entregues a você quando o aplicativo não está aberto',
|
||||
Quote: 'Citar',
|
||||
Reactions_are_disabled: 'Reagir está desabilitado',
|
||||
|
|
|
@ -154,7 +154,7 @@ export default {
|
|||
DELETE: 'УДАЛИТЬ',
|
||||
description: 'описание',
|
||||
Description: 'Описание',
|
||||
DESKTOP_OPTIONS: 'ПАРАМЕТРЫ РАБОЧЕГО СТОЛА',
|
||||
Desktop_Options: 'Параметры Рабочего Стола',
|
||||
Directory: 'Директория',
|
||||
Direct_Messages: 'Личные сообщения',
|
||||
Disable_notifications: 'Отключить уведомления',
|
||||
|
@ -166,8 +166,7 @@ export default {
|
|||
edited: 'отредактировано',
|
||||
Edit: 'Редактировать',
|
||||
Email_or_password_field_is_empty: 'Поле электронной почты или пароля пусты',
|
||||
Email: 'Email',
|
||||
EMAIL: 'EMAIL',
|
||||
Email: 'E-mail',
|
||||
email: 'e-mail',
|
||||
Enable_Auto_Translate: 'Включить автоперевод',
|
||||
Enable_notifications: 'Включить уведомления',
|
||||
|
@ -192,7 +191,7 @@ export default {
|
|||
Has_joined_the_channel: 'Присоединился к каналу',
|
||||
Has_joined_the_conversation: 'Присоединился к беседе',
|
||||
Has_left_the_channel: 'Покинул канал',
|
||||
IN_APP_AND_DESKTOP: 'В приложении и на десктопе',
|
||||
In_App_And_Desktop: 'В приложении и на десктопе',
|
||||
In_App_and_Desktop_Alert_info: 'Отображает баннер в верхней части экрана, когда приложение открыто, и отображает уведомление на рабочем столе.',
|
||||
Invisible: 'Невидимый',
|
||||
Invite: 'Приглашение',
|
||||
|
@ -283,7 +282,7 @@ export default {
|
|||
Profile: 'Профиль',
|
||||
Public_Channel: 'Публичный канал',
|
||||
Public: 'Публичный',
|
||||
PUSH_NOTIFICATIONS: 'PUSH УВЕДОМЛЕНИЯ',
|
||||
Push_Notifications: 'Push Уведомления',
|
||||
Push_Notifications_Alert_Info: 'Эти уведомления доставляются вам, когда приложение не открыто',
|
||||
Quote: 'Цитата',
|
||||
Reactions_are_disabled: 'Реакции отключены',
|
||||
|
|
|
@ -100,7 +100,6 @@ export default {
|
|||
announcement: '公告',
|
||||
Announcement: '公告',
|
||||
Apply_Your_Certificate: '使用自己的凭证',
|
||||
Applying_a_theme_will_change_how_the_app_looks: '套用主题将会改变 App 的外观',
|
||||
ARCHIVE: '封存',
|
||||
archive: '封存',
|
||||
are_typing: '正在输入',
|
||||
|
@ -184,8 +183,8 @@ export default {
|
|||
deleting_room: '正在删除聊天室',
|
||||
description: '描述',
|
||||
Description: '描述',
|
||||
DESKTOP_OPTIONS: '桌面选项',
|
||||
DESKTOP_NOTIFICATIONS: '桌面通知',
|
||||
Desktop_Options: '桌面选项',
|
||||
Desktop_Notifications: '桌面通知',
|
||||
Desktop_Alert_info: '这些通知将发送至桌面',
|
||||
Directory: '目录',
|
||||
Direct_Messages: '私訊',
|
||||
|
@ -213,7 +212,6 @@ export default {
|
|||
Email_Notification_Mode_Disabled: '禁用',
|
||||
Email_or_password_field_is_empty: '邮件或密码字段为空',
|
||||
Email: '邮箱',
|
||||
EMAIL: 'EMAIL',
|
||||
email: '邮箱',
|
||||
Empty_title: '空白标题',
|
||||
Enable_Auto_Translate: '开启自动翻译',
|
||||
|
@ -270,7 +268,7 @@ export default {
|
|||
I_Saved_My_E2E_Password: '保存我的 E2E 密码',
|
||||
IP: 'IP',
|
||||
In_app: 'App 内',
|
||||
IN_APP_AND_DESKTOP: 'App 内及桌面',
|
||||
In_App_And_Desktop: 'App 内及桌面',
|
||||
In_App_and_Desktop_Alert_info: '打开应用程序时,在屏幕顶部显示横幅,并在桌面上显示通知',
|
||||
Invisible: '隐身',
|
||||
Invite: '邀请',
|
||||
|
@ -397,7 +395,7 @@ export default {
|
|||
Profile: '个人资料',
|
||||
Public_Channel: '公共频道',
|
||||
Public: '公共',
|
||||
PUSH_NOTIFICATIONS: '推送通知',
|
||||
Push_Notifications: '推送通知',
|
||||
Push_Notifications_Alert_Info: '这些通知将在未开启 App 时发送给您',
|
||||
Quote: '引用',
|
||||
Reactions_are_disabled: '表情貼被禁用',
|
||||
|
|
|
@ -100,7 +100,6 @@ export default {
|
|||
announcement: '公告',
|
||||
Announcement: '公告',
|
||||
Apply_Your_Certificate: '使用自己的憑證',
|
||||
Applying_a_theme_will_change_how_the_app_looks: '套用主題將會改變 App 的外觀',
|
||||
ARCHIVE: '封存',
|
||||
archive: '封存',
|
||||
are_typing: '正在輸入',
|
||||
|
@ -184,8 +183,8 @@ export default {
|
|||
deleting_room: '正在刪除聊天室',
|
||||
description: '描述',
|
||||
Description: '描述',
|
||||
DESKTOP_OPTIONS: '桌面選項',
|
||||
DESKTOP_NOTIFICATIONS: '桌面通知',
|
||||
Desktop_Options: '桌面選項',
|
||||
Desktop_Notifications: '桌面通知',
|
||||
Desktop_Alert_info: '這些通知將發送至桌面',
|
||||
Directory: '目錄',
|
||||
Direct_Messages: '私訊',
|
||||
|
@ -213,7 +212,6 @@ export default {
|
|||
Email_Notification_Mode_Disabled: '禁用',
|
||||
Email_or_password_field_is_empty: '電子郵件或密碼字段為空',
|
||||
Email: '電子郵件',
|
||||
EMAIL: 'EMAIL',
|
||||
email: '電子郵件',
|
||||
Empty_title: '空白標題',
|
||||
Enable_Auto_Translate: '開啟自動翻譯',
|
||||
|
@ -270,7 +268,7 @@ export default {
|
|||
I_Saved_My_E2E_Password: '儲存我的 E2E 密碼',
|
||||
IP: 'IP',
|
||||
In_app: 'App 內',
|
||||
IN_APP_AND_DESKTOP: 'App 內及桌面',
|
||||
In_App_And_Desktop: 'App 內及桌面',
|
||||
In_App_and_Desktop_Alert_info: '當在應用程序打開時,螢幕頂端顯示橫幅,並在桌面上顯示通知',
|
||||
Invisible: '隱身',
|
||||
Invite: '邀請',
|
||||
|
@ -397,7 +395,7 @@ export default {
|
|||
Profile: '個人資料',
|
||||
Public_Channel: '公共頻道',
|
||||
Public: '公共',
|
||||
PUSH_NOTIFICATIONS: '推送通知',
|
||||
Push_Notifications: '推送通知',
|
||||
Push_Notifications_Alert_Info: '這些通知將在未開啟 App 時發送給您',
|
||||
Quote: '引用',
|
||||
Reactions_are_disabled: '表情貼被禁用',
|
||||
|
|
28
app/index.js
28
app/index.js
|
@ -68,7 +68,9 @@ export default class Root extends React.Component {
|
|||
if (!isFDroidBuild) {
|
||||
this.initCrashReport();
|
||||
}
|
||||
const { width, height, scale } = Dimensions.get('window');
|
||||
const {
|
||||
width, height, scale, fontScale
|
||||
} = Dimensions.get('window');
|
||||
this.state = {
|
||||
theme: defaultTheme(),
|
||||
themePreferences: {
|
||||
|
@ -77,7 +79,8 @@ export default class Root extends React.Component {
|
|||
},
|
||||
width,
|
||||
height,
|
||||
scale
|
||||
scale,
|
||||
fontScale
|
||||
};
|
||||
if (isTablet) {
|
||||
this.initTablet();
|
||||
|
@ -134,8 +137,14 @@ export default class Root extends React.Component {
|
|||
};
|
||||
|
||||
// Dimensions update fires twice
|
||||
onDimensionsChange = debounce(({ window: { width, height, scale } }) => {
|
||||
this.setDimensions({ width, height, scale });
|
||||
onDimensionsChange = debounce(({
|
||||
window: {
|
||||
width, height, scale, fontScale
|
||||
}
|
||||
}) => {
|
||||
this.setDimensions({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
this.setMasterDetail(width);
|
||||
})
|
||||
|
||||
|
@ -148,8 +157,12 @@ export default class Root extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
setDimensions = ({ width, height, scale }) => {
|
||||
this.setState({ width, height, scale });
|
||||
setDimensions = ({
|
||||
width, height, scale, fontScale
|
||||
}) => {
|
||||
this.setState({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
}
|
||||
|
||||
initTablet = () => {
|
||||
|
@ -176,7 +189,7 @@ export default class Root extends React.Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
themePreferences, theme, width, height, scale
|
||||
themePreferences, theme, width, height, scale, fontScale
|
||||
} = this.state;
|
||||
return (
|
||||
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
||||
|
@ -194,6 +207,7 @@ export default class Root extends React.Component {
|
|||
width,
|
||||
height,
|
||||
scale,
|
||||
fontScale,
|
||||
setDimensions: this.setDimensions
|
||||
}}
|
||||
>
|
||||
|
|
28
app/share.js
28
app/share.js
|
@ -117,7 +117,9 @@ App.propTypes = {
|
|||
class Root extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { width, height, scale } = Dimensions.get('screen');
|
||||
const {
|
||||
width, height, scale, fontScale
|
||||
} = Dimensions.get('screen');
|
||||
this.state = {
|
||||
theme: defaultTheme(),
|
||||
themePreferences: {
|
||||
|
@ -127,7 +129,8 @@ class Root extends React.Component {
|
|||
root: '',
|
||||
width,
|
||||
height,
|
||||
scale
|
||||
scale,
|
||||
fontScale
|
||||
};
|
||||
this.init();
|
||||
}
|
||||
|
@ -166,18 +169,28 @@ class Root extends React.Component {
|
|||
}
|
||||
|
||||
// Dimensions update fires twice
|
||||
onDimensionsChange = debounce(({ window: { width, height, scale } }) => {
|
||||
this.setDimensions({ width, height, scale });
|
||||
onDimensionsChange = debounce(({
|
||||
window: {
|
||||
width, height, scale, fontScale
|
||||
}
|
||||
}) => {
|
||||
this.setDimensions({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
this.setMasterDetail(width);
|
||||
})
|
||||
|
||||
setDimensions = ({ width, height, scale }) => {
|
||||
this.setState({ width, height, scale });
|
||||
setDimensions = ({
|
||||
width, height, scale, fontScale
|
||||
}) => {
|
||||
this.setState({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
theme, root, width, height, scale
|
||||
theme, root, width, height, scale, fontScale
|
||||
} = this.state;
|
||||
const navTheme = navigationTheme(theme);
|
||||
return (
|
||||
|
@ -189,6 +202,7 @@ class Root extends React.Component {
|
|||
width,
|
||||
height,
|
||||
scale,
|
||||
fontScale,
|
||||
setDimensions: this.setDimensions
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -18,18 +18,17 @@ class AdminPanelView extends React.Component {
|
|||
|
||||
static propTypes = {
|
||||
baseUrl: PropTypes.string,
|
||||
token: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
token: PropTypes.string
|
||||
}
|
||||
|
||||
render() {
|
||||
const { baseUrl, token, theme } = this.props;
|
||||
const { baseUrl, token } = this.props;
|
||||
if (!baseUrl) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<SafeAreaView theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView>
|
||||
<StatusBar />
|
||||
<WebView
|
||||
// https://github.com/react-native-community/react-native-webview/issues/1311
|
||||
onMessage={() => {}}
|
||||
|
|
|
@ -28,7 +28,7 @@ const styles = StyleSheet.create({
|
|||
|
||||
const AuthLoadingView = React.memo(({ theme, text }) => (
|
||||
<View style={[styles.container, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
{text && (
|
||||
<>
|
||||
<ActivityIndicator color={themes[theme].auxiliaryText} size='large' />
|
||||
|
|
|
@ -155,7 +155,7 @@ class AuthenticationWebView extends React.PureComponent {
|
|||
|
||||
return (
|
||||
<>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<WebView
|
||||
source={{ uri: url }}
|
||||
userAgent={userAgent}
|
||||
|
|
|
@ -1,53 +1,22 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, Switch, View, StyleSheet, ScrollView
|
||||
} from 'react-native';
|
||||
import { FlatList, Switch, StyleSheet } from 'react-native';
|
||||
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import I18n from '../../i18n';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import sharedStyles from '../Styles';
|
||||
import ListItem from '../../containers/ListItem';
|
||||
import Separator from '../../containers/Separator';
|
||||
import * as List from '../../containers/List';
|
||||
import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import { withTheme } from '../../theme';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import { logEvent, events } from '../../utils/log';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
contentContainerStyle: {
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
marginTop: 10,
|
||||
paddingBottom: 30
|
||||
},
|
||||
flatListContainerStyle: {
|
||||
borderBottomWidth: StyleSheet.hairlineWidth
|
||||
},
|
||||
sectionSeparator: {
|
||||
...sharedStyles.separatorVertical,
|
||||
height: 10
|
||||
list: {
|
||||
paddingTop: 16
|
||||
}
|
||||
});
|
||||
|
||||
const SectionSeparator = React.memo(({ theme }) => (
|
||||
<View
|
||||
style={[
|
||||
styles.sectionSeparator,
|
||||
{
|
||||
backgroundColor: themes[theme].auxiliaryBackground,
|
||||
borderColor: themes[theme].separatorColor
|
||||
}
|
||||
]}
|
||||
/>
|
||||
));
|
||||
|
||||
SectionSeparator.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
class AutoTranslateView extends React.Component {
|
||||
static navigationOptions = () => ({
|
||||
title: I18n.t('Auto_Translate')
|
||||
|
@ -55,8 +24,7 @@ class AutoTranslateView extends React.Component {
|
|||
|
||||
static propTypes = {
|
||||
route: PropTypes.object,
|
||||
theme: PropTypes.string,
|
||||
navigation: PropTypes.object
|
||||
theme: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -135,14 +103,9 @@ class AutoTranslateView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
renderSeparator = () => {
|
||||
const { theme } = this.props;
|
||||
return <Separator theme={theme} />;
|
||||
}
|
||||
|
||||
renderIcon = () => {
|
||||
const { theme } = this.props;
|
||||
return <CustomIcon name='check' size={20} style={{ color: themes[theme].tintColor }} />;
|
||||
return <List.Icon name='check' style={{ color: themes[theme].tintColor }} />;
|
||||
}
|
||||
|
||||
renderSwitch = () => {
|
||||
|
@ -158,54 +121,46 @@ class AutoTranslateView extends React.Component {
|
|||
|
||||
renderItem = ({ item }) => {
|
||||
const { selectedLanguage } = this.state;
|
||||
const { theme } = this.props;
|
||||
const { language, name } = item;
|
||||
const isSelected = selectedLanguage === language;
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
<List.Item
|
||||
title={name || language}
|
||||
onPress={() => this.saveAutoTranslateLanguage(language)}
|
||||
testID={`auto-translate-view-${ language }`}
|
||||
right={isSelected ? this.renderIcon : null}
|
||||
theme={theme}
|
||||
translateTitle={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { languages } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='auto-translate-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<ScrollView
|
||||
{...scrollPersistTaps}
|
||||
contentContainerStyle={[
|
||||
styles.contentContainerStyle,
|
||||
{
|
||||
backgroundColor: themes[theme].auxiliaryBackground,
|
||||
borderColor: themes[theme].separatorColor
|
||||
}
|
||||
]}
|
||||
testID='auto-translate-view-list'
|
||||
>
|
||||
<ListItem
|
||||
title={I18n.t('Enable_Auto_Translate')}
|
||||
testID='auto-translate-view-switch'
|
||||
right={() => this.renderSwitch()}
|
||||
theme={theme}
|
||||
/>
|
||||
<SectionSeparator theme={theme} />
|
||||
<SafeAreaView testID='auto-translate-view'>
|
||||
<StatusBar />
|
||||
<List.Container testID='auto-translate-view-list'>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Enable_Auto_Translate'
|
||||
testID='auto-translate-view-switch'
|
||||
right={() => this.renderSwitch()}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
<FlatList
|
||||
data={languages}
|
||||
extraData={this.state}
|
||||
keyExtractor={item => item.language}
|
||||
renderItem={this.renderItem}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
contentContainerStyle={[styles.flatListContainerStyle, { borderColor: themes[theme].separatorColor }]}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
ListFooterComponent={List.Separator}
|
||||
ListHeaderComponent={List.Separator}
|
||||
contentContainerStyle={[List.styles.contentContainerStyleFlatList, styles.list]}
|
||||
/>
|
||||
</ScrollView>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -323,8 +323,8 @@ class CreateChannelView extends React.Component {
|
|||
contentContainerStyle={[sharedStyles.container, styles.container]}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='create-channel-view' theme={theme}>
|
||||
<StatusBar />
|
||||
<SafeAreaView testID='create-channel-view'>
|
||||
<ScrollView {...scrollPersistTaps}>
|
||||
<View style={[sharedStyles.separatorVertical, { borderColor: themes[theme].separatorColor }]}>
|
||||
<TextInput
|
||||
|
|
|
@ -151,8 +151,8 @@ class CreateChannelView extends React.Component {
|
|||
contentContainerStyle={styles.container}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='create-discussion-view' style={styles.container} theme={theme}>
|
||||
<StatusBar />
|
||||
<SafeAreaView testID='create-discussion-view' style={styles.container}>
|
||||
<ScrollView {...scrollPersistTaps}>
|
||||
<Text style={[styles.description, { color: themes[theme].auxiliaryText }]}>{I18n.t('Discussion_Desc')}</Text>
|
||||
<SelectChannel
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
StyleSheet, FlatList, View, Text, Linking
|
||||
} from 'react-native';
|
||||
import { FlatList, Linking } from 'react-native';
|
||||
|
||||
import I18n from '../i18n';
|
||||
import { withTheme } from '../theme';
|
||||
import { themes } from '../constants/colors';
|
||||
import sharedStyles from './Styles';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import Separator from '../containers/Separator';
|
||||
import ListItem from '../containers/ListItem';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import * as List from '../containers/List';
|
||||
import { DEFAULT_BROWSER_KEY } from '../utils/openLink';
|
||||
import { isIOS } from '../utils/deviceInfo';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
|
@ -44,21 +39,6 @@ const BROWSERS = [
|
|||
}
|
||||
];
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
list: {
|
||||
paddingBottom: 18
|
||||
},
|
||||
info: {
|
||||
paddingTop: 25,
|
||||
paddingBottom: 18,
|
||||
paddingHorizontal: 16
|
||||
},
|
||||
infoText: {
|
||||
fontSize: 16,
|
||||
...sharedStyles.textRegular
|
||||
}
|
||||
});
|
||||
|
||||
class DefaultBrowserView extends React.Component {
|
||||
static navigationOptions = () => ({
|
||||
title: I18n.t('Default_browser')
|
||||
|
@ -120,59 +100,44 @@ class DefaultBrowserView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
renderSeparator = () => {
|
||||
const { theme } = this.props;
|
||||
return <Separator theme={theme} />;
|
||||
}
|
||||
|
||||
renderIcon = () => {
|
||||
const { theme } = this.props;
|
||||
return <CustomIcon name='check' size={20} color={themes[theme].tintColor} />;
|
||||
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => {
|
||||
const { theme } = this.props;
|
||||
const { title, value } = item;
|
||||
return (
|
||||
<ListItem
|
||||
<List.Item
|
||||
title={I18n.t(title, { defaultValue: title })}
|
||||
onPress={() => this.changeDefaultBrowser(value)}
|
||||
testID={`default-browser-view-${ title }`}
|
||||
right={this.isSelected(value) ? this.renderIcon : null}
|
||||
theme={theme}
|
||||
translateTitle={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderHeader = () => {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<>
|
||||
<View style={styles.info}>
|
||||
<Text style={[styles.infoText, { color: themes[theme].infoText }]}>{I18n.t('Choose_where_you_want_links_be_opened')}</Text>
|
||||
</View>
|
||||
{this.renderSeparator()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
renderHeader = () => (
|
||||
<>
|
||||
<List.Header title='Choose_where_you_want_links_be_opened' />
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
|
||||
render() {
|
||||
const { supported } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='default-browser-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='default-browser-view'>
|
||||
<StatusBar />
|
||||
<FlatList
|
||||
data={DEFAULT_BROWSERS.concat(supported)}
|
||||
keyExtractor={item => item.value}
|
||||
contentContainerStyle={[
|
||||
styles.list,
|
||||
{ borderColor: themes[theme].separatorColor }
|
||||
]}
|
||||
contentContainerStyle={List.styles.contentContainerStyleFlatList}
|
||||
renderItem={this.renderItem}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
ListFooterComponent={this.renderSeparator}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
ListFooterComponent={List.Separator}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
|
|
@ -240,9 +240,8 @@ class DirectoryView extends React.Component {
|
|||
<SafeAreaView
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
testID='directory-view'
|
||||
theme={theme}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<FlatList
|
||||
data={data}
|
||||
style={styles.list}
|
||||
|
|
|
@ -62,9 +62,9 @@ class E2EEnterYourPasswordView extends React.Component {
|
|||
contentContainerStyle={sharedStyles.container}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<ScrollView {...scrollPersistTaps} style={sharedStyles.container} contentContainerStyle={[sharedStyles.containerScrollView, styles.scrollView]}>
|
||||
<SafeAreaView theme={theme} style={[styles.container, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<SafeAreaView style={[styles.container, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<TextInput
|
||||
inputRef={(e) => { this.passwordInput = e; }}
|
||||
placeholder={I18n.t('Password')}
|
||||
|
|
|
@ -43,7 +43,6 @@ class E2EHowItWorksView extends React.Component {
|
|||
<SafeAreaView
|
||||
style={[styles.container, { backgroundColor: themes[theme].backgroundColor }]}
|
||||
testID='e2e-how-it-works-view'
|
||||
theme={theme}
|
||||
>
|
||||
<Markdown
|
||||
msg={I18n.t('E2E_How_It_Works_info1')}
|
||||
|
|
|
@ -126,8 +126,8 @@ class E2ESaveYourPasswordView extends React.Component {
|
|||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<SafeAreaView theme={theme} style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar />
|
||||
<ScrollView {...scrollPersistTaps} style={sharedStyles.container} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||
<View style={[styles.container, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<Text style={[styles.warning, { color: themes[theme].dangerColor }]}>{I18n.t('Save_Your_Encryption_Password_warning')}</Text>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ScrollView, View } from 'react-native';
|
||||
import { View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import RNPickerSelect from 'react-native-picker-select';
|
||||
|
||||
|
@ -8,15 +8,13 @@ import {
|
|||
inviteLinksSetParams as inviteLinksSetParamsAction,
|
||||
inviteLinksCreate as inviteLinksCreateAction
|
||||
} from '../../actions/inviteLinks';
|
||||
import ListItem from '../../containers/ListItem';
|
||||
import * as List from '../../containers/List';
|
||||
import styles from './styles';
|
||||
import Button from '../../containers/Button';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import I18n from '../../i18n';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import Separator from '../../containers/Separator';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import { logEvent, events } from '../../utils/log';
|
||||
|
||||
|
@ -62,7 +60,6 @@ class InviteUsersView extends React.Component {
|
|||
navigation: PropTypes.object,
|
||||
route: PropTypes.object,
|
||||
theme: PropTypes.string,
|
||||
timeDateFormat: PropTypes.string,
|
||||
createInviteLink: PropTypes.func,
|
||||
inviteLinksSetParams: PropTypes.func
|
||||
}
|
||||
|
@ -110,29 +107,23 @@ class InviteUsersView extends React.Component {
|
|||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }} theme={theme}>
|
||||
<ScrollView
|
||||
{...scrollPersistTaps}
|
||||
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Expiration_Days')}
|
||||
right={() => this.renderPicker('days', 'Never')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Max_number_of_uses')}
|
||||
right={() => this.renderPicker('maxUses', 'No_limit')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<SafeAreaView>
|
||||
<List.Container>
|
||||
<StatusBar />
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Expiration_Days'
|
||||
right={() => this.renderPicker('days', 'Never')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Max_number_of_uses'
|
||||
right={() => this.renderPicker('maxUses', 'No_limit')}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
<View style={styles.innerContainer}>
|
||||
<View style={[styles.divider, { backgroundColor: themes[theme].separatorColor }]} />
|
||||
<Button
|
||||
title={I18n.t('Generate_New_Link')}
|
||||
type='primary'
|
||||
|
@ -140,7 +131,7 @@ class InviteUsersView extends React.Component {
|
|||
theme={theme}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,36 +1,12 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
import { PADDING_HORIZONTAL } from '../../containers/List/constants';
|
||||
|
||||
import sharedStyles from '../Styles';
|
||||
|
||||
export default StyleSheet.create({
|
||||
innerContainer: {
|
||||
paddingHorizontal: 20
|
||||
},
|
||||
divider: {
|
||||
width: '100%',
|
||||
height: StyleSheet.hairlineWidth,
|
||||
marginVertical: 20
|
||||
},
|
||||
sectionSeparatorBorder: {
|
||||
height: 10
|
||||
},
|
||||
marginBottom: {
|
||||
height: 30
|
||||
},
|
||||
contentContainer: {
|
||||
marginVertical: 10
|
||||
},
|
||||
infoText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 13,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10
|
||||
},
|
||||
sectionTitle: {
|
||||
...sharedStyles.separatorBottom,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10,
|
||||
fontSize: 14
|
||||
paddingHorizontal: PADDING_HORIZONTAL,
|
||||
paddingTop: 16
|
||||
},
|
||||
viewContainer: {
|
||||
justifyContent: 'center'
|
||||
|
|
|
@ -102,14 +102,14 @@ class InviteUsersView extends React.Component {
|
|||
theme, invite
|
||||
} = this.props;
|
||||
return (
|
||||
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }} theme={theme}>
|
||||
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<ScrollView
|
||||
{...scrollPersistTaps}
|
||||
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<View style={styles.innerContainer}>
|
||||
<RCTextInput
|
||||
label={I18n.t('Invite_Link')}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
import { PADDING_HORIZONTAL } from '../../containers/List/constants';
|
||||
|
||||
export default StyleSheet.create({
|
||||
innerContainer: {
|
||||
padding: 20,
|
||||
padding: PADDING_HORIZONTAL,
|
||||
paddingBottom: 0
|
||||
},
|
||||
divider: {
|
||||
|
|
|
@ -9,10 +9,7 @@ import { showErrorAlert } from '../../utils/info';
|
|||
import log, { logEvent, events } from '../../utils/log';
|
||||
import { setUser as setUserAction } from '../../actions/login';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import sharedStyles from '../Styles';
|
||||
import ListItem from '../../containers/ListItem';
|
||||
import Separator from '../../containers/Separator';
|
||||
import * as List from '../../containers/List';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import { appStart as appStartAction, ROOT_LOADING, ROOT_INSIDE } from '../../actions/app';
|
||||
|
@ -108,50 +105,39 @@ class LanguageView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
renderSeparator = () => {
|
||||
const { theme } = this.props;
|
||||
return <Separator theme={theme} />;
|
||||
}
|
||||
|
||||
renderIcon = () => {
|
||||
const { theme } = this.props;
|
||||
return <CustomIcon name='check' size={20} style={{ color: themes[theme].tintColor }} />;
|
||||
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => {
|
||||
const { value, label } = item;
|
||||
const { language } = this.state;
|
||||
const { theme } = this.props;
|
||||
const isSelected = language === value;
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
<List.Item
|
||||
title={label}
|
||||
onPress={() => this.submit(value)}
|
||||
testID={`language-view-${ value }`}
|
||||
right={isSelected ? this.renderIcon : null}
|
||||
theme={theme}
|
||||
translateTitle={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='language-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='language-view'>
|
||||
<StatusBar />
|
||||
<FlatList
|
||||
data={LANGUAGES}
|
||||
keyExtractor={item => item.value}
|
||||
contentContainerStyle={[
|
||||
sharedStyles.listContentContainer,
|
||||
{
|
||||
backgroundColor: themes[theme].auxiliaryBackground,
|
||||
borderColor: themes[theme].separatorColor
|
||||
}
|
||||
]}
|
||||
ListHeaderComponent={List.Separator}
|
||||
ListFooterComponent={List.Separator}
|
||||
contentContainerStyle={List.styles.contentContainerStyleFlatList}
|
||||
renderItem={this.renderItem}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
|
|
@ -1,51 +1,13 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text, ScrollView, View, StyleSheet
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import Touch from '../utils/touch';
|
||||
import sharedStyles from './Styles';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
import I18n from '../i18n';
|
||||
import DisclosureIndicator from '../containers/DisclosureIndicator';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import { themes } from '../constants/colors';
|
||||
import openLink from '../utils/openLink';
|
||||
import { withTheme } from '../theme';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scroll: {
|
||||
marginTop: 35,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth
|
||||
},
|
||||
separator: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
width: '100%',
|
||||
marginLeft: 20
|
||||
},
|
||||
item: {
|
||||
width: '100%',
|
||||
height: 48,
|
||||
paddingLeft: 20,
|
||||
paddingRight: 10,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
text: {
|
||||
...sharedStyles.textMedium,
|
||||
fontSize: 18
|
||||
}
|
||||
});
|
||||
|
||||
const Separator = ({ theme }) => <View style={[styles.separator, { backgroundColor: themes[theme].separatorColor }]} />;
|
||||
Separator.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
import * as List from '../containers/List';
|
||||
|
||||
class LegalView extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -61,40 +23,29 @@ class LegalView extends React.Component {
|
|||
openLink(`${ server }/${ route }`, theme);
|
||||
}
|
||||
|
||||
renderItem = ({ text, route, testID }) => {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<Touch
|
||||
style={[styles.item, { backgroundColor: themes[theme].backgroundColor }]}
|
||||
onPress={() => this.onPressItem({ route })}
|
||||
testID={testID}
|
||||
theme={theme}
|
||||
>
|
||||
<Text style={[styles.text, { color: themes[theme].titleText }]}>{I18n.t(text)}</Text>
|
||||
<DisclosureIndicator theme={theme} />
|
||||
</Touch>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='legal-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<ScrollView
|
||||
contentContainerStyle={[
|
||||
styles.scroll,
|
||||
{
|
||||
backgroundColor: themes[theme].backgroundColor,
|
||||
borderColor: themes[theme].separatorColor
|
||||
}
|
||||
]}
|
||||
{...scrollPersistTaps}
|
||||
>
|
||||
{this.renderItem({ text: 'Terms_of_Service', route: 'terms-of-service', testID: 'legal-terms-button' })}
|
||||
<Separator theme={theme} />
|
||||
{this.renderItem({ text: 'Privacy_Policy', route: 'privacy-policy', testID: 'legal-privacy-button' })}
|
||||
</ScrollView>
|
||||
<SafeAreaView testID='legal-view'>
|
||||
<StatusBar />
|
||||
<List.Container>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Terms_of_Service'
|
||||
onPress={() => this.onPressItem({ route: 'terms-of-service' })}
|
||||
testID='legal-terms-button'
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Privacy_Policy'
|
||||
onPress={() => this.onPressItem({ route: 'privacy-policy' })}
|
||||
testID='legal-privacy-button'
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ const LivechatEditView = ({
|
|||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} style={styles.container}>
|
||||
<SafeAreaView theme={theme}>
|
||||
<SafeAreaView>
|
||||
<Title
|
||||
title={visitor?.username}
|
||||
theme={theme}
|
||||
|
|
|
@ -296,9 +296,8 @@ class MessagesView extends React.Component {
|
|||
<SafeAreaView
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
testID={this.content.testID}
|
||||
theme={theme}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<FlatList
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -261,11 +261,10 @@ class NewMessageView extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
render = () => {
|
||||
const { theme } = this.props;
|
||||
render() {
|
||||
return (
|
||||
<SafeAreaView testID='new-message-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='new-message-view'>
|
||||
<StatusBar />
|
||||
{this.renderList()}
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
|
|
@ -3,9 +3,9 @@ import { View, FlatList, StyleSheet } from 'react-native';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import TextInput from '../../../containers/TextInput';
|
||||
import * as List from '../../../containers/List';
|
||||
import { themes } from '../../../constants/colors';
|
||||
import Item from './Item';
|
||||
import Separator from '../../../containers/Separator';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -64,7 +64,7 @@ const ServerInput = ({
|
|||
<FlatList
|
||||
data={serversHistory}
|
||||
renderItem={({ item }) => <Item item={item} theme={theme} onPress={() => onPressServerHistory(item)} onDelete={onDelete} />}
|
||||
ItemSeparatorComponent={() => <Separator theme={theme} />}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</View>
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Text
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const Info = React.memo(({ info, theme }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.infoText,
|
||||
{
|
||||
color: themes[theme].infoText,
|
||||
backgroundColor: themes[theme].auxiliaryBackground
|
||||
}
|
||||
]}
|
||||
>
|
||||
{info}
|
||||
</Text>
|
||||
));
|
||||
|
||||
Info.propTypes = {
|
||||
info: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default Info;
|
|
@ -1,23 +0,0 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
View
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const SectionSeparator = React.memo(({ theme }) => (
|
||||
<View
|
||||
style={[
|
||||
styles.sectionSeparatorBorder,
|
||||
{ backgroundColor: themes[theme].auxiliaryBackground }
|
||||
]}
|
||||
/>
|
||||
));
|
||||
|
||||
SectionSeparator.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default SectionSeparator;
|
|
@ -1,29 +0,0 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Text
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const SectionTitle = React.memo(({ title, theme }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.sectionTitle,
|
||||
{
|
||||
backgroundColor: themes[theme].auxiliaryBackground,
|
||||
color: themes[theme].infoText
|
||||
}
|
||||
]}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
));
|
||||
|
||||
SectionTitle.propTypes = {
|
||||
title: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default SectionTitle;
|
|
@ -1,26 +1,26 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
View, ScrollView, Switch, Text
|
||||
} from 'react-native';
|
||||
import { Switch, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import database from '../../lib/database';
|
||||
import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import ListItem from '../../containers/ListItem';
|
||||
import Separator from '../../containers/Separator';
|
||||
import * as List from '../../containers/List';
|
||||
import I18n from '../../i18n';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import styles from './styles';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import { withTheme } from '../../theme';
|
||||
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import log, { events, logEvent } from '../../utils/log';
|
||||
import SectionTitle from './SectionTitle';
|
||||
import SectionSeparator from './SectionSeparator';
|
||||
import Info from './Info';
|
||||
import { OPTIONS } from './options';
|
||||
import sharedStyles from '../Styles';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
pickerText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 16
|
||||
}
|
||||
});
|
||||
|
||||
class NotificationPreferencesView extends React.Component {
|
||||
static navigationOptions = () => ({
|
||||
|
@ -132,120 +132,103 @@ class NotificationPreferencesView extends React.Component {
|
|||
|
||||
render() {
|
||||
const { room } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='notification-preference-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<ScrollView
|
||||
{...scrollPersistTaps}
|
||||
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
testID='notification-preference-view-list'
|
||||
>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Receive_Notification')}
|
||||
testID='notification-preference-view-receive-notification'
|
||||
right={() => this.renderSwitch('disableNotifications')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('Receive_notifications_from', { name: room.name })} theme={theme} />
|
||||
<SectionSeparator theme={theme} />
|
||||
<SafeAreaView testID='notification-preference-view'>
|
||||
<StatusBar />
|
||||
<List.Container testID='notification-preference-view-list'>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Receive_Notification'
|
||||
testID='notification-preference-view-receive-notification'
|
||||
right={() => this.renderSwitch('disableNotifications')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info={I18n.t('Receive_notifications_from', { name: room.name })} translateInfo={false} />
|
||||
</List.Section>
|
||||
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Receive_Group_Mentions')}
|
||||
testID='notification-preference-view-group-mentions'
|
||||
right={() => this.renderSwitch('muteGroupMentions')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('Receive_Group_Mentions_Info')} theme={theme} />
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Receive_Group_Mentions'
|
||||
testID='notification-preference-view-group-mentions'
|
||||
right={() => this.renderSwitch('muteGroupMentions')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='Receive_Group_Mentions_Info' />
|
||||
</List.Section>
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Show_Unread_Counter')}
|
||||
testID='notification-preference-view-unread-count'
|
||||
right={() => this.renderSwitch('hideUnreadStatus')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('Show_Unread_Counter_Info')} theme={theme} />
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Show_Unread_Counter'
|
||||
testID='notification-preference-view-unread-count'
|
||||
right={() => this.renderSwitch('hideUnreadStatus')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='Show_Unread_Counter_Info' />
|
||||
</List.Section>
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<SectionTitle title={I18n.t('IN_APP_AND_DESKTOP')} theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
<List.Section title='In_App_And_Desktop'>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Alert'
|
||||
testID='notification-preference-view-alert'
|
||||
onPress={title => this.pickerSelection(title, 'desktopNotifications')}
|
||||
right={() => this.renderPickerOption('desktopNotifications')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='In_App_and_Desktop_Alert_info' />
|
||||
</List.Section>
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Alert')}
|
||||
testID='notification-preference-view-alert'
|
||||
onPress={title => this.pickerSelection(title, 'desktopNotifications')}
|
||||
right={() => this.renderPickerOption('desktopNotifications')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('In_App_and_Desktop_Alert_info')} theme={theme} />
|
||||
<List.Section title='Push_Notifications'>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Alert'
|
||||
testID='notification-preference-view-push-notification'
|
||||
onPress={title => this.pickerSelection(title, 'mobilePushNotifications')}
|
||||
right={() => this.renderPickerOption('mobilePushNotifications')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='Push_Notifications_Alert_Info' />
|
||||
</List.Section>
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<SectionTitle title={I18n.t('PUSH_NOTIFICATIONS')} theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
<List.Section title='Desktop_Options'>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Audio'
|
||||
testID='notification-preference-view-audio'
|
||||
onPress={title => this.pickerSelection(title, 'audioNotifications')}
|
||||
right={() => this.renderPickerOption('audioNotifications')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Sound'
|
||||
testID='notification-preference-view-sound'
|
||||
onPress={title => this.pickerSelection(title, 'audioNotificationValue')}
|
||||
right={() => this.renderPickerOption('audioNotificationValue')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Notification_Duration'
|
||||
testID='notification-preference-view-notification-duration'
|
||||
onPress={title => this.pickerSelection(title, 'desktopNotificationDuration')}
|
||||
right={() => this.renderPickerOption('desktopNotificationDuration')}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Alert')}
|
||||
testID='notification-preference-view-push-notification'
|
||||
onPress={title => this.pickerSelection(title, 'mobilePushNotifications')}
|
||||
right={() => this.renderPickerOption('mobilePushNotifications')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('Push_Notifications_Alert_Info')} theme={theme} />
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<SectionTitle title={I18n.t('DESKTOP_OPTIONS')} theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Audio')}
|
||||
testID='notification-preference-view-audio'
|
||||
onPress={title => this.pickerSelection(title, 'audioNotifications')}
|
||||
right={() => this.renderPickerOption('audioNotifications')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Sound')}
|
||||
testID='notification-preference-view-sound'
|
||||
onPress={title => this.pickerSelection(title, 'audioNotificationValue')}
|
||||
right={() => this.renderPickerOption('audioNotificationValue')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Notification_Duration')}
|
||||
testID='notification-preference-view-notification-duration'
|
||||
onPress={title => this.pickerSelection(title, 'desktopNotificationDuration')}
|
||||
right={() => this.renderPickerOption('desktopNotificationDuration')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<SectionTitle title={I18n.t('EMAIL')} theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Alert')}
|
||||
testID='notification-preference-view-email-alert'
|
||||
onPress={title => this.pickerSelection(title, 'emailNotifications')}
|
||||
right={() => this.renderPickerOption('emailNotifications')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
|
||||
<View style={[styles.marginBottom, { backgroundColor: themes[theme].auxiliaryBackground }]} />
|
||||
</ScrollView>
|
||||
<List.Section title='Email'>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Alert'
|
||||
testID='notification-preference-view-email-alert'
|
||||
onPress={title => this.pickerSelection(title, 'emailNotifications')}
|
||||
right={() => this.renderPickerOption('emailNotifications')}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import sharedStyles from '../Styles';
|
||||
|
||||
export default StyleSheet.create({
|
||||
sectionSeparatorBorder: {
|
||||
height: 10
|
||||
},
|
||||
marginBottom: {
|
||||
height: 30
|
||||
},
|
||||
contentContainer: {
|
||||
marginVertical: 10
|
||||
},
|
||||
infoText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 13,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10
|
||||
},
|
||||
sectionTitle: {
|
||||
...sharedStyles.separatorBottom,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10,
|
||||
fontSize: 14
|
||||
},
|
||||
pickerText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 16
|
||||
}
|
||||
});
|
|
@ -10,15 +10,11 @@ import { themes } from '../constants/colors';
|
|||
import debounce from '../utils/debounce';
|
||||
import sharedStyles from './Styles';
|
||||
|
||||
import ListItem from '../containers/ListItem';
|
||||
import Check from '../containers/Check';
|
||||
import Separator from '../containers/Separator';
|
||||
import * as List from '../containers/List';
|
||||
import SearchBox from '../containers/SearchBox';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
check: {
|
||||
marginHorizontal: 0
|
||||
},
|
||||
search: {
|
||||
width: '100%',
|
||||
height: 56
|
||||
|
@ -28,10 +24,6 @@ const styles = StyleSheet.create({
|
|||
paddingVertical: 56,
|
||||
...sharedStyles.textAlignCenter,
|
||||
...sharedStyles.textSemibold
|
||||
},
|
||||
withoutBorder: {
|
||||
borderBottomWidth: 0,
|
||||
borderTopWidth: 0
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -41,11 +33,11 @@ const Item = React.memo(({
|
|||
onItemPress,
|
||||
theme
|
||||
}) => (
|
||||
<ListItem
|
||||
<List.Item
|
||||
title={I18n.t(item.label, { defaultValue: item.label, second: item?.second })}
|
||||
right={selected && (() => <Check theme={theme} style={styles.check} />)}
|
||||
right={selected && (() => <List.Icon name='check' color={themes[theme].tintColor} />)}
|
||||
onPress={onItemPress}
|
||||
theme={theme}
|
||||
translateTitle={false}
|
||||
/>
|
||||
));
|
||||
Item.propTypes = {
|
||||
|
@ -109,7 +101,7 @@ class PickerView extends React.PureComponent {
|
|||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<SafeAreaView>
|
||||
{this.renderSearch()}
|
||||
<FlatList
|
||||
data={data}
|
||||
|
@ -122,19 +114,13 @@ class PickerView extends React.PureComponent {
|
|||
onItemPress={() => this.onChangeValue(item.value)}
|
||||
/>
|
||||
)}
|
||||
ItemSeparatorComponent={() => <Separator theme={theme} />}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
ListHeaderComponent={List.Separator}
|
||||
ListFooterComponent={List.Separator}
|
||||
ListEmptyComponent={() => <Text style={[styles.noResult, { color: themes[theme].titleText }]}>{I18n.t('No_results_found')}</Text>}
|
||||
contentContainerStyle={[
|
||||
sharedStyles.listContentContainer,
|
||||
{
|
||||
backgroundColor: themes[theme].auxiliaryBackground,
|
||||
borderColor: themes[theme].separatorColor
|
||||
},
|
||||
!data.length && styles.withoutBorder
|
||||
]}
|
||||
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
|
||||
contentContainerStyle={[List.styles.contentContainerStyleFlatList]}
|
||||
/>
|
||||
</>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -469,8 +469,8 @@ class ProfileView extends React.Component {
|
|||
contentContainerStyle={sharedStyles.container}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='profile-view' theme={theme}>
|
||||
<StatusBar />
|
||||
<SafeAreaView testID='profile-view'>
|
||||
<ScrollView
|
||||
contentContainerStyle={sharedStyles.containerScrollView}
|
||||
testID='profile-view-list'
|
||||
|
|
|
@ -135,8 +135,8 @@ class ReadReceiptView extends React.Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView testID='read-receipt-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='read-receipt-view'>
|
||||
<StatusBar />
|
||||
{loading
|
||||
? <ActivityIndicator theme={theme} />
|
||||
: (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, SectionList, Text, Alert, Share, Switch
|
||||
View, Text, Alert, Share, Switch
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import _ from 'lodash';
|
||||
|
@ -13,24 +13,22 @@ import styles from './styles';
|
|||
import sharedStyles from '../Styles';
|
||||
import Avatar from '../../containers/Avatar';
|
||||
import Status from '../../containers/Status';
|
||||
import * as List from '../../containers/List';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import log, { logEvent, events } from '../../utils/log';
|
||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||
import I18n from '../../i18n';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import DisclosureIndicator from '../../containers/DisclosureIndicator';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import { themes, SWITCH_TRACK_COLOR } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import { CloseModalButton } from '../../containers/HeaderButton';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import Markdown from '../../containers/markdown';
|
||||
import { showConfirmationAlert, showErrorAlert } from '../../utils/info';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import { E2E_ROOM_TYPES } from '../../lib/encryption/constants';
|
||||
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
||||
import database from '../../lib/database';
|
||||
import { withDimensions } from '../../dimensions';
|
||||
|
||||
class RoomActionsView extends React.Component {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }) => {
|
||||
|
@ -44,19 +42,15 @@ class RoomActionsView extends React.Component {
|
|||
}
|
||||
|
||||
static propTypes = {
|
||||
baseUrl: PropTypes.string,
|
||||
navigation: PropTypes.object,
|
||||
route: PropTypes.object,
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
token: PropTypes.string
|
||||
}),
|
||||
leaveRoom: PropTypes.func,
|
||||
jitsiEnabled: PropTypes.bool,
|
||||
e2eEnabled: PropTypes.bool,
|
||||
setLoadingInvite: PropTypes.func,
|
||||
closeRoom: PropTypes.func,
|
||||
theme: PropTypes.string
|
||||
theme: PropTypes.string,
|
||||
fontScale: PropTypes.number
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -240,281 +234,6 @@ class RoomActionsView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
get sections() {
|
||||
const {
|
||||
room, member, membersCount, canViewMembers, canAddUser, canInviteUser, joined, canAutoTranslate, canForwardGuest, canReturnQueue, canEdit
|
||||
} = this.state;
|
||||
const { jitsiEnabled, e2eEnabled } = this.props;
|
||||
const {
|
||||
rid, t, blocker, encrypted
|
||||
} = room;
|
||||
const isGroupChat = RocketChat.isGroupChat(room);
|
||||
|
||||
const notificationsAction = {
|
||||
icon: 'notification',
|
||||
name: I18n.t('Notifications'),
|
||||
route: 'NotificationPrefView',
|
||||
params: { rid, room },
|
||||
testID: 'room-actions-notifications',
|
||||
right: this.renderDisclosure
|
||||
};
|
||||
|
||||
const jitsiActions = jitsiEnabled ? [
|
||||
{
|
||||
icon: 'phone',
|
||||
name: I18n.t('Voice_call'),
|
||||
event: () => RocketChat.callJitsi(rid, true),
|
||||
testID: 'room-actions-voice',
|
||||
right: this.renderDisclosure
|
||||
},
|
||||
{
|
||||
icon: 'camera',
|
||||
name: I18n.t('Video_call'),
|
||||
event: () => RocketChat.callJitsi(rid),
|
||||
testID: 'room-actions-video',
|
||||
right: this.renderDisclosure
|
||||
}
|
||||
] : [];
|
||||
|
||||
const sections = [{
|
||||
data: [{
|
||||
icon: 'star',
|
||||
name: I18n.t('Room_Info'),
|
||||
route: 'RoomInfoView',
|
||||
// forward room only if room isn't joined
|
||||
params: {
|
||||
rid, t, room, member
|
||||
},
|
||||
disabled: isGroupChat,
|
||||
testID: 'room-actions-info'
|
||||
}],
|
||||
renderItem: this.renderRoomInfo
|
||||
}, {
|
||||
data: jitsiActions,
|
||||
renderItem: this.renderItem
|
||||
}, {
|
||||
data: [
|
||||
{
|
||||
icon: 'attach',
|
||||
name: I18n.t('Files'),
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Files' },
|
||||
testID: 'room-actions-files',
|
||||
right: this.renderDisclosure
|
||||
},
|
||||
{
|
||||
icon: 'mention',
|
||||
name: I18n.t('Mentions'),
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Mentions' },
|
||||
testID: 'room-actions-mentioned',
|
||||
right: this.renderDisclosure
|
||||
},
|
||||
{
|
||||
icon: 'star',
|
||||
name: I18n.t('Starred'),
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Starred' },
|
||||
testID: 'room-actions-starred',
|
||||
right: this.renderDisclosure
|
||||
},
|
||||
{
|
||||
icon: 'search',
|
||||
name: I18n.t('Search'),
|
||||
route: 'SearchMessagesView',
|
||||
params: { rid, encrypted },
|
||||
testID: 'room-actions-search',
|
||||
right: this.renderDisclosure
|
||||
},
|
||||
{
|
||||
icon: 'share',
|
||||
name: I18n.t('Share'),
|
||||
event: this.handleShare,
|
||||
testID: 'room-actions-share',
|
||||
right: this.renderDisclosure
|
||||
},
|
||||
{
|
||||
icon: 'pin',
|
||||
name: I18n.t('Pinned'),
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Pinned' },
|
||||
testID: 'room-actions-pinned',
|
||||
right: this.renderDisclosure
|
||||
}
|
||||
],
|
||||
renderItem: this.renderItem
|
||||
}];
|
||||
|
||||
if (canAutoTranslate) {
|
||||
sections[2].data.push({
|
||||
icon: 'language',
|
||||
name: I18n.t('Auto_Translate'),
|
||||
route: 'AutoTranslateView',
|
||||
params: { rid, room },
|
||||
testID: 'room-actions-auto-translate',
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
|
||||
if (isGroupChat) {
|
||||
sections[2].data.unshift({
|
||||
icon: 'team',
|
||||
name: I18n.t('Members'),
|
||||
description: membersCount > 0 ? `${ membersCount } ${ I18n.t('members') }` : null,
|
||||
route: 'RoomMembersView',
|
||||
params: { rid, room },
|
||||
testID: 'room-actions-members',
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
|
||||
if (t === 'd' && !isGroupChat) {
|
||||
sections.push({
|
||||
data: [
|
||||
{
|
||||
icon: 'ban',
|
||||
name: I18n.t(`${ blocker ? 'Unblock' : 'Block' }_user`),
|
||||
type: 'danger',
|
||||
event: this.toggleBlockUser,
|
||||
testID: 'room-actions-block-user',
|
||||
right: this.renderDisclosure
|
||||
}
|
||||
],
|
||||
renderItem: this.renderItem
|
||||
});
|
||||
sections[2].data.push(notificationsAction);
|
||||
} else if (t === 'c' || t === 'p') {
|
||||
const actions = [];
|
||||
|
||||
if (canViewMembers) {
|
||||
actions.push({
|
||||
icon: 'team',
|
||||
name: I18n.t('Members'),
|
||||
description: membersCount > 0 ? `${ membersCount } ${ I18n.t('members') }` : null,
|
||||
route: 'RoomMembersView',
|
||||
params: { rid, room },
|
||||
testID: 'room-actions-members',
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
|
||||
if (canAddUser) {
|
||||
actions.push({
|
||||
icon: 'add',
|
||||
name: I18n.t('Add_users'),
|
||||
route: 'SelectedUsersView',
|
||||
params: {
|
||||
rid,
|
||||
title: I18n.t('Add_users'),
|
||||
nextAction: this.addUser
|
||||
},
|
||||
testID: 'room-actions-add-user',
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
if (canInviteUser) {
|
||||
actions.push({
|
||||
icon: 'user-add',
|
||||
name: I18n.t('Invite_users'),
|
||||
route: 'InviteUsersView',
|
||||
params: {
|
||||
rid
|
||||
},
|
||||
testID: 'room-actions-invite-user',
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
sections[2].data = [...actions, ...sections[2].data];
|
||||
|
||||
if (joined) {
|
||||
sections[2].data.push(notificationsAction);
|
||||
sections.push({
|
||||
data: [
|
||||
{
|
||||
icon: 'logout',
|
||||
name: I18n.t('Leave_channel'),
|
||||
type: 'danger',
|
||||
event: this.leaveChannel,
|
||||
testID: 'room-actions-leave-channel',
|
||||
right: this.renderDisclosure
|
||||
}
|
||||
],
|
||||
renderItem: this.renderItem
|
||||
});
|
||||
}
|
||||
} else if (t === 'l') {
|
||||
sections[2].data = [];
|
||||
|
||||
if (!this.isOmnichannelPreview) {
|
||||
sections[2].data.push({
|
||||
icon: 'close',
|
||||
name: I18n.t('Close'),
|
||||
event: this.closeLivechat,
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
|
||||
if (canForwardGuest) {
|
||||
sections[2].data.push({
|
||||
icon: 'user-forward',
|
||||
name: I18n.t('Forward'),
|
||||
route: 'ForwardLivechatView',
|
||||
params: { rid },
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
|
||||
if (canReturnQueue) {
|
||||
sections[2].data.push({
|
||||
icon: 'undo',
|
||||
name: I18n.t('Return'),
|
||||
event: this.returnLivechat,
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
|
||||
sections[2].data.push({
|
||||
icon: 'history',
|
||||
name: I18n.t('Navigation_history'),
|
||||
route: 'VisitorNavigationView',
|
||||
params: { rid },
|
||||
right: this.renderDisclosure
|
||||
});
|
||||
}
|
||||
|
||||
sections.push({
|
||||
data: [notificationsAction],
|
||||
renderItem: this.renderItem
|
||||
});
|
||||
}
|
||||
|
||||
// If can edit this room
|
||||
// If this room type can be Encrypted
|
||||
// If e2e is enabled for this server
|
||||
if (canEdit && E2E_ROOM_TYPES[t] && e2eEnabled) {
|
||||
sections.splice(2, 0, {
|
||||
data: [{
|
||||
icon: 'encrypted',
|
||||
name: I18n.t('Encrypted'),
|
||||
testID: 'room-actions-encrypt',
|
||||
right: this.renderEncryptedSwitch
|
||||
}],
|
||||
renderItem: this.renderItem
|
||||
});
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
renderDisclosure = () => {
|
||||
const { theme } = this.props;
|
||||
return <DisclosureIndicator theme={theme} />;
|
||||
}
|
||||
|
||||
renderSeparator = () => {
|
||||
const { theme } = this.props;
|
||||
return <View style={[styles.separator, { backgroundColor: themes[theme].separatorColor }]} />;
|
||||
}
|
||||
|
||||
renderEncryptedSwitch = () => {
|
||||
const { room } = this.state;
|
||||
const { encrypted } = room;
|
||||
|
@ -523,7 +242,6 @@ class RoomActionsView extends React.Component {
|
|||
value={encrypted}
|
||||
trackColor={SWITCH_TRACK_COLOR}
|
||||
onValueChange={this.toggleEncrypted}
|
||||
style={styles.encryptedSwitch}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -667,128 +385,467 @@ class RoomActionsView extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
renderRoomInfo = ({ item }) => {
|
||||
renderRoomInfo = () => {
|
||||
const { room, member } = this.state;
|
||||
const {
|
||||
name,
|
||||
t,
|
||||
rid,
|
||||
topic
|
||||
rid, name, t, topic
|
||||
} = room;
|
||||
const { theme } = this.props;
|
||||
const { theme, fontScale } = this.props;
|
||||
|
||||
const avatar = RocketChat.getRoomAvatar(room);
|
||||
const isGroupChat = RocketChat.isGroupChat(room);
|
||||
|
||||
return (
|
||||
this.renderTouchableItem((
|
||||
<>
|
||||
<Avatar
|
||||
text={avatar}
|
||||
style={styles.avatar}
|
||||
size={50}
|
||||
type={t}
|
||||
rid={rid}
|
||||
>
|
||||
{t === 'd' && member._id ? <Status style={sharedStyles.status} id={member._id} /> : null }
|
||||
</Avatar>
|
||||
<View style={[styles.roomTitleContainer, item.disabled && styles.roomTitlePadding]}>
|
||||
{room.t === 'd'
|
||||
? <Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{room.fname}</Text>
|
||||
: (
|
||||
<View style={styles.roomTitleRow}>
|
||||
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} status={room.visitor?.status} theme={theme} />
|
||||
<Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{RocketChat.getRoomTitle(room)}</Text>
|
||||
</View>
|
||||
)
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<Touch
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'RoomInfoView',
|
||||
// forward room only if room isn't joined
|
||||
params: {
|
||||
rid, t, room, member
|
||||
}
|
||||
<Markdown
|
||||
preview
|
||||
msg={t === 'd' ? `@${ name }` : topic}
|
||||
style={[styles.roomDescription, { color: themes[theme].auxiliaryText }]}
|
||||
numberOfLines={1}
|
||||
theme={theme}
|
||||
/>
|
||||
{room.t === 'd' && <Markdown msg={member.statusText} style={[styles.roomDescription, { color: themes[theme].auxiliaryText }]} preview theme={theme} numberOfLines={1} />}
|
||||
})}
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
accessibilityLabel={I18n.t('Room_Info')}
|
||||
accessibilityTraits='button'
|
||||
enabled={!isGroupChat}
|
||||
testID='room-actions-info'
|
||||
theme={theme}
|
||||
>
|
||||
<View style={[styles.roomInfoContainer, { height: 72 * fontScale }]}>
|
||||
<Avatar
|
||||
text={avatar}
|
||||
style={styles.avatar}
|
||||
size={50}
|
||||
type={t}
|
||||
rid={rid}
|
||||
>
|
||||
{t === 'd' && member._id ? <Status style={sharedStyles.status} id={member._id} /> : null }
|
||||
</Avatar>
|
||||
<View style={styles.roomTitleContainer}>
|
||||
{room.t === 'd'
|
||||
? <Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{room.fname}</Text>
|
||||
: (
|
||||
<View style={styles.roomTitleRow}>
|
||||
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} status={room.visitor?.status} theme={theme} />
|
||||
<Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{RocketChat.getRoomTitle(room)}</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
<Markdown
|
||||
preview
|
||||
msg={t === 'd' ? `@${ name }` : topic}
|
||||
style={[styles.roomDescription, { color: themes[theme].auxiliaryText }]}
|
||||
numberOfLines={1}
|
||||
theme={theme}
|
||||
/>
|
||||
{room.t === 'd' && <Markdown msg={member.statusText} style={[styles.roomDescription, { color: themes[theme].auxiliaryText }]} preview theme={theme} numberOfLines={1} />}
|
||||
</View>
|
||||
{isGroupChat ? null : <List.Icon name='chevron-right' />}
|
||||
</View>
|
||||
{!item.disabled && <DisclosureIndicator theme={theme} />}
|
||||
</>
|
||||
), item)
|
||||
</Touch>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
);
|
||||
}
|
||||
|
||||
renderTouchableItem = (subview, item) => {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<Touch
|
||||
onPress={() => this.onPressTouchable(item)}
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
accessibilityLabel={item.name}
|
||||
accessibilityTraits='button'
|
||||
enabled={!item.disabled}
|
||||
testID={item.testID}
|
||||
theme={theme}
|
||||
>
|
||||
<View style={styles.sectionItem}>
|
||||
{subview}
|
||||
</View>
|
||||
</Touch>
|
||||
);
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => {
|
||||
const { theme } = this.props;
|
||||
const colorDanger = { color: themes[theme].dangerColor };
|
||||
const subview = item.type === 'danger' ? (
|
||||
<>
|
||||
<CustomIcon name={item.icon} size={24} style={[styles.sectionItemIcon, colorDanger]} />
|
||||
<Text style={[styles.sectionItemName, colorDanger]}>{ item.name }</Text>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CustomIcon name={item.icon} size={24} style={[styles.sectionItemIcon, { color: themes[theme].bodyText }]} />
|
||||
<Text style={[styles.sectionItemName, { color: themes[theme].bodyText }]}>{ item.name }</Text>
|
||||
{item.description ? <Text style={[styles.sectionItemDescription, { color: themes[theme].auxiliaryText }]}>{ item.description }</Text> : null}
|
||||
{item?.right?.()}
|
||||
</>
|
||||
);
|
||||
return this.renderTouchableItem(subview, item);
|
||||
}
|
||||
|
||||
renderSectionSeparator = (data) => {
|
||||
const { theme } = this.props;
|
||||
if (data.trailingItem) {
|
||||
return <View style={[styles.sectionSeparator, data.leadingSection && styles.sectionSeparatorBorder, { backgroundColor: themes[theme].auxiliaryBackground, borderColor: themes[theme].separatorColor }]} />;
|
||||
renderJitsi = () => {
|
||||
const { room } = this.state;
|
||||
const { jitsiEnabled } = this.props;
|
||||
if (!jitsiEnabled) {
|
||||
return null;
|
||||
}
|
||||
if (!data.trailingSection) {
|
||||
return <View style={[styles.sectionSeparatorBorder, { backgroundColor: themes[theme].auxiliaryBackground, borderColor: themes[theme].separatorColor }]} />;
|
||||
return (
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Voice_call'
|
||||
onPress={() => RocketChat.callJitsi(room?.rid, true)}
|
||||
testID='room-actions-voice'
|
||||
left={() => <List.Icon name='phone' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Video_call'
|
||||
onPress={() => RocketChat.callJitsi(room?.rid)}
|
||||
testID='room-actions-video'
|
||||
left={() => <List.Icon name='camera' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
);
|
||||
}
|
||||
|
||||
renderE2EEncryption = () => {
|
||||
const {
|
||||
room, canEdit
|
||||
} = this.state;
|
||||
const { e2eEnabled } = this.props;
|
||||
|
||||
// If can edit this room
|
||||
// If this room type can be Encrypted
|
||||
// If e2e is enabled for this server
|
||||
if (canEdit && E2E_ROOM_TYPES[room?.t] && e2eEnabled) {
|
||||
return (
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Encrypted'
|
||||
testID='room-actions-encrypt'
|
||||
left={() => <List.Icon name='encrypted' />}
|
||||
right={this.renderEncryptedSwitch}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
renderLastSection = () => {
|
||||
const { room, joined } = this.state;
|
||||
const { theme } = this.props;
|
||||
const { t, blocker } = room;
|
||||
|
||||
if (!joined || t === 'l') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (t === 'd') {
|
||||
return (
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={`${ blocker ? 'Unblock' : 'Block' }_user`}
|
||||
onPress={() => this.onPressTouchable({
|
||||
event: this.toggleBlockUser
|
||||
})}
|
||||
testID='room-actions-block-user'
|
||||
left={() => <List.Icon name='ban' color={themes[theme].dangerColor} />}
|
||||
showActionIndicator
|
||||
color={themes[theme].dangerColor}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
);
|
||||
}
|
||||
|
||||
if (t === 'p' || t === 'c') {
|
||||
return (
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Leave_channel'
|
||||
onPress={() => this.onPressTouchable({
|
||||
event: this.leaveChannel
|
||||
})}
|
||||
testID='room-actions-leave-channel'
|
||||
left={() => <List.Icon name='logout' color={themes[theme].dangerColor} />}
|
||||
showActionIndicator
|
||||
color={themes[theme].dangerColor}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
room, membersCount, canViewMembers, canAddUser, canInviteUser, joined, canAutoTranslate, canForwardGuest, canReturnQueue
|
||||
} = this.state;
|
||||
const {
|
||||
rid, t, encrypted
|
||||
} = room;
|
||||
const isGroupChat = RocketChat.isGroupChat(room);
|
||||
return (
|
||||
<SafeAreaView testID='room-actions-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SectionList
|
||||
contentContainerStyle={[styles.contentContainer, { backgroundColor: themes[theme].auxiliaryBackground }]}
|
||||
style={[styles.container, { backgroundColor: themes[theme].auxiliaryBackground }]}
|
||||
stickySectionHeadersEnabled={false}
|
||||
sections={this.sections}
|
||||
SectionSeparatorComponent={this.renderSectionSeparator}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
keyExtractor={item => item.name}
|
||||
testID='room-actions-list'
|
||||
{...scrollPersistTaps}
|
||||
/>
|
||||
<SafeAreaView testID='room-actions-view'>
|
||||
<StatusBar />
|
||||
<List.Container>
|
||||
{this.renderRoomInfo()}
|
||||
{this.renderJitsi()}
|
||||
{this.renderE2EEncryption()}
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
|
||||
{(['c', 'p'].includes(t) && canViewMembers) || isGroupChat
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Members'
|
||||
subtitle={membersCount > 0 ? `${ membersCount } ${ I18n.t('members') }` : null}
|
||||
onPress={() => this.onPressTouchable({ route: 'RoomMembersView', params: { rid, room } })}
|
||||
testID='room-actions-members'
|
||||
left={() => <List.Icon name='team' />}
|
||||
showActionIndicator
|
||||
translateSubtitle={false}
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p'].includes(t) && canAddUser
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Add_users'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'SelectedUsersView',
|
||||
params: {
|
||||
rid,
|
||||
title: I18n.t('Add_users'),
|
||||
nextAction: this.addUser
|
||||
}
|
||||
})}
|
||||
testID='room-actions-add-user'
|
||||
left={() => <List.Icon name='add' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p'].includes(t) && canInviteUser
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Invite_users'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'InviteUsersView',
|
||||
params: { rid }
|
||||
})}
|
||||
testID='room-actions-invite-user'
|
||||
left={() => <List.Icon name='user-add' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t)
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Files'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Files' }
|
||||
})}
|
||||
testID='room-actions-files'
|
||||
left={() => <List.Icon name='attach' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t)
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Mentions'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Mentions' }
|
||||
})}
|
||||
testID='room-actions-mentioned'
|
||||
left={() => <List.Icon name='mention' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t)
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Starred'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Starred' }
|
||||
})}
|
||||
testID='room-actions-starred'
|
||||
left={() => <List.Icon name='star' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t)
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Search'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'SearchMessagesView',
|
||||
params: { rid, encrypted }
|
||||
})}
|
||||
testID='room-actions-search'
|
||||
left={() => <List.Icon name='search' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t)
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Share'
|
||||
onPress={() => this.onPressTouchable({
|
||||
event: this.handleShare
|
||||
})}
|
||||
testID='room-actions-share'
|
||||
left={() => <List.Icon name='share' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t)
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Pinned'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'MessagesView',
|
||||
params: { rid, t, name: 'Pinned' }
|
||||
})}
|
||||
testID='room-actions-pinned'
|
||||
left={() => <List.Icon name='pin' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t) && canAutoTranslate
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Auto_Translate'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'AutoTranslateView',
|
||||
params: { rid, room }
|
||||
})}
|
||||
testID='room-actions-auto-translate'
|
||||
left={() => <List.Icon name='language' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['c', 'p', 'd'].includes(t) && joined
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Notifications'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'NotificationPrefView',
|
||||
params: { rid, room }
|
||||
})}
|
||||
testID='room-actions-notifications'
|
||||
left={() => <List.Icon name='notification' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['l'].includes(t) && !this.isOmnichannelPreview
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Close'
|
||||
onPress={() => this.onPressTouchable({
|
||||
event: this.closeLivechat
|
||||
})}
|
||||
left={() => <List.Icon name='close' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['l'].includes(t) && !this.isOmnichannelPreview && canForwardGuest
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Forward'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'ForwardLivechatView',
|
||||
params: { rid }
|
||||
})}
|
||||
left={() => <List.Icon name='user-forward' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['l'].includes(t) && !this.isOmnichannelPreview && canReturnQueue
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Return'
|
||||
onPress={() => this.onPressTouchable({
|
||||
event: this.returnLivechat
|
||||
})}
|
||||
left={() => <List.Icon name='undo' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
|
||||
{['l'].includes(t) && !this.isOmnichannelPreview
|
||||
? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Navigation_history'
|
||||
onPress={() => this.onPressTouchable({
|
||||
route: 'VisitorNavigationView',
|
||||
params: { rid }
|
||||
})}
|
||||
left={() => <List.Icon name='history' />}
|
||||
showActionIndicator
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
</List.Section>
|
||||
|
||||
{this.renderLastSection()}
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
user: getUserSelector(state),
|
||||
baseUrl: state.server.server,
|
||||
jitsiEnabled: state.settings.Jitsi_Enabled || false,
|
||||
e2eEnabled: state.settings.E2E_Enable || false
|
||||
});
|
||||
|
@ -799,4 +856,4 @@ const mapDispatchToProps = dispatch => ({
|
|||
setLoadingInvite: loading => dispatch(setLoadingAction(loading))
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(RoomActionsView));
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(withDimensions(RoomActionsView)));
|
||||
|
|
|
@ -1,51 +1,20 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
import { PADDING_HORIZONTAL } from '../../containers/List/constants';
|
||||
|
||||
import sharedStyles from '../Styles';
|
||||
|
||||
export default StyleSheet.create({
|
||||
contentContainer: {
|
||||
paddingBottom: 30
|
||||
},
|
||||
container: {
|
||||
flex: 1
|
||||
},
|
||||
sectionItem: {
|
||||
paddingVertical: 11,
|
||||
roomInfoContainer: {
|
||||
paddingHorizontal: PADDING_HORIZONTAL,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
sectionItemIcon: {
|
||||
width: 56,
|
||||
textAlign: 'center'
|
||||
},
|
||||
sectionItemName: {
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
sectionItemDescription: {
|
||||
fontSize: 14,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
separator: {
|
||||
height: StyleSheet.hairlineWidth
|
||||
},
|
||||
sectionSeparator: {
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
height: 36
|
||||
},
|
||||
sectionSeparatorBorder: {
|
||||
borderTopWidth: StyleSheet.hairlineWidth
|
||||
},
|
||||
avatar: {
|
||||
marginHorizontal: 16
|
||||
marginRight: PADDING_HORIZONTAL
|
||||
},
|
||||
roomTitleContainer: {
|
||||
flex: 1
|
||||
},
|
||||
roomTitlePadding: {
|
||||
paddingRight: 16
|
||||
},
|
||||
roomTitle: {
|
||||
fontSize: 16,
|
||||
...sharedStyles.textMedium
|
||||
|
@ -58,8 +27,5 @@ export default StyleSheet.create({
|
|||
paddingRight: 16,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
encryptedSwitch: {
|
||||
marginHorizontal: 16
|
||||
}
|
||||
});
|
||||
|
|
|
@ -418,10 +418,9 @@ class RoomInfoEditView extends React.Component {
|
|||
contentContainerStyle={sharedStyles.container}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<SafeAreaView
|
||||
testID='room-info-edit-view'
|
||||
theme={theme}
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
>
|
||||
<ScrollView
|
||||
|
|
|
@ -350,10 +350,9 @@ class RoomInfoView extends React.Component {
|
|||
const { theme } = this.props;
|
||||
return (
|
||||
<ScrollView style={[styles.scroll, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<SafeAreaView
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
theme={theme}
|
||||
testID='room-info-view'
|
||||
>
|
||||
<View style={[styles.avatarContainer, this.isDirect && styles.avatarContainerDirectRoom, { backgroundColor: themes[theme].auxiliaryBackground }]}>
|
||||
|
|
|
@ -250,8 +250,8 @@ class RoomMembersView extends React.Component {
|
|||
} = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='room-members-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='room-members-view'>
|
||||
<StatusBar />
|
||||
<FlatList
|
||||
data={filtering ? membersFiltered : members}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -1020,9 +1020,8 @@ class RoomView extends React.Component {
|
|||
<SafeAreaView
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
testID='room-view'
|
||||
theme={theme}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<Banner
|
||||
rid={rid}
|
||||
title={I18n.t('Announcement')}
|
||||
|
|
|
@ -1008,8 +1008,8 @@ class RoomsListView extends React.Component {
|
|||
} = this.props;
|
||||
|
||||
return (
|
||||
<SafeAreaView testID='rooms-list-view' theme={theme} style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='rooms-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar />
|
||||
{this.renderHeader()}
|
||||
{this.renderScroll()}
|
||||
{showSortDropdown ? (
|
||||
|
|
|
@ -1,32 +1,19 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet, Switch, ScrollView } from 'react-native';
|
||||
import { Switch } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import I18n from '../i18n';
|
||||
import { withTheme } from '../theme';
|
||||
import { themes, SWITCH_TRACK_COLOR } from '../constants/colors';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import Separator from '../containers/Separator';
|
||||
import ListItem from '../containers/ListItem';
|
||||
import ItemInfo from '../containers/ItemInfo';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import * as List from '../containers/List';
|
||||
import database from '../lib/database';
|
||||
import { supportedBiometryLabel, changePasscode, checkHasPasscode } from '../utils/localAuthentication';
|
||||
import { DisclosureImage } from '../containers/DisclosureIndicator';
|
||||
import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
import { events, logEvent } from '../utils/log';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
listPadding: {
|
||||
paddingVertical: 36
|
||||
},
|
||||
emptySpace: {
|
||||
marginTop: 36
|
||||
}
|
||||
});
|
||||
|
||||
const DEFAULT_BIOMETRY = false;
|
||||
|
||||
class ScreenLockConfigView extends React.Component {
|
||||
|
@ -161,29 +148,23 @@ class ScreenLockConfigView extends React.Component {
|
|||
this.setState({ autoLockTime }, () => this.save());
|
||||
}
|
||||
|
||||
renderSeparator = () => {
|
||||
const { theme } = this.props;
|
||||
return <Separator theme={theme} />;
|
||||
}
|
||||
|
||||
renderIcon = () => {
|
||||
const { theme } = this.props;
|
||||
return <CustomIcon name='check' size={20} color={themes[theme].tintColor} />;
|
||||
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => {
|
||||
const { theme } = this.props;
|
||||
const { title, value, disabled } = item;
|
||||
return (
|
||||
<>
|
||||
<ListItem
|
||||
<List.Item
|
||||
title={title}
|
||||
onPress={() => this.changeAutoLockTime(value)}
|
||||
right={this.isSelected(value) ? this.renderIcon : null}
|
||||
theme={theme}
|
||||
disabled={disabled}
|
||||
translateTitle={false}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<List.Separator />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -214,7 +195,7 @@ class ScreenLockConfigView extends React.Component {
|
|||
|
||||
renderAutoLockItems = () => {
|
||||
const { autoLock, autoLockTime } = this.state;
|
||||
const { theme, Force_Screen_Lock_After, Force_Screen_Lock } = this.props;
|
||||
const { Force_Screen_Lock_After, Force_Screen_Lock } = this.props;
|
||||
if (!autoLock) {
|
||||
return null;
|
||||
}
|
||||
|
@ -233,75 +214,62 @@ class ScreenLockConfigView extends React.Component {
|
|||
});
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Separator style={styles.emptySpace} theme={theme} />
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
{items.map(item => this.renderItem({ item }))}
|
||||
</>
|
||||
</List.Section>
|
||||
);
|
||||
}
|
||||
|
||||
renderDisclosure = () => {
|
||||
const { theme } = this.props;
|
||||
return <DisclosureImage theme={theme} />;
|
||||
}
|
||||
|
||||
renderBiometry = () => {
|
||||
const { autoLock, biometryLabel } = this.state;
|
||||
const { theme } = this.props;
|
||||
if (!autoLock || !biometryLabel) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={I18n.t('Local_authentication_unlock_with_label', { label: biometryLabel })}
|
||||
right={() => this.renderBiometrySwitch()}
|
||||
theme={theme}
|
||||
translateTitle={false}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
</>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { autoLock } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<ScrollView
|
||||
keyExtractor={item => item.value}
|
||||
contentContainerStyle={styles.listPadding}
|
||||
>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Local_authentication_unlock_option')}
|
||||
right={() => this.renderAutoLockSwitch()}
|
||||
theme={theme}
|
||||
/>
|
||||
{autoLock
|
||||
? (
|
||||
<>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Local_authentication_change_passcode')}
|
||||
theme={theme}
|
||||
right={this.renderDisclosure}
|
||||
onPress={this.changePasscode}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
: null
|
||||
}
|
||||
<Separator theme={theme} />
|
||||
<ItemInfo
|
||||
info={I18n.t('Local_authentication_info')}
|
||||
theme={theme}
|
||||
/>
|
||||
<SafeAreaView>
|
||||
<StatusBar />
|
||||
<List.Container>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Local_authentication_unlock_option'
|
||||
right={() => this.renderAutoLockSwitch()}
|
||||
/>
|
||||
{autoLock
|
||||
? (
|
||||
<>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Local_authentication_change_passcode'
|
||||
onPress={this.changePasscode}
|
||||
showActionIndicator
|
||||
/>
|
||||
</>
|
||||
)
|
||||
: null
|
||||
}
|
||||
<List.Separator />
|
||||
<List.Info info='Local_authentication_info' />
|
||||
</List.Section>
|
||||
{this.renderBiometry()}
|
||||
{this.renderAutoLockItems()}
|
||||
</ScrollView>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -183,8 +183,8 @@ class SearchMessagesView extends React.Component {
|
|||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }} testID='search-messages-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }} testID='search-messages-view'>
|
||||
<StatusBar />
|
||||
<View style={styles.searchContainer}>
|
||||
<RCTextInput
|
||||
autoFocus
|
||||
|
|
|
@ -83,8 +83,8 @@ class SelectServerView extends React.Component {
|
|||
const { servers } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView>
|
||||
<StatusBar />
|
||||
<View style={[styles.list, { borderColor: themes[theme].separatorColor }]}>
|
||||
<FlatList
|
||||
data={servers}
|
||||
|
|
|
@ -307,10 +307,10 @@ class SelectedUsersView extends React.Component {
|
|||
}
|
||||
|
||||
render = () => {
|
||||
const { loading, theme } = this.props;
|
||||
const { loading } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='select-users-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='select-users-view'>
|
||||
<StatusBar />
|
||||
{this.renderList()}
|
||||
<Loading visible={loading} />
|
||||
</SafeAreaView>
|
||||
|
|
|
@ -104,9 +104,9 @@ class SetUsernameView extends React.Component {
|
|||
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
|
||||
contentContainerStyle={sharedStyles.container}
|
||||
>
|
||||
<StatusBar theme={theme} />
|
||||
<StatusBar />
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||
<SafeAreaView testID='set-username-view' theme={theme}>
|
||||
<SafeAreaView testID='set-username-view'>
|
||||
<Text
|
||||
style={[
|
||||
sharedStyles.loginTitle,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
View, Linking, ScrollView, Switch, Share, Clipboard
|
||||
Linking, Switch, Share, Clipboard
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
@ -14,19 +14,14 @@ import { toggleCrashReport as toggleCrashReportAction, toggleAnalyticsEvents as
|
|||
import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
|
||||
import { DrawerButton, CloseModalButton } from '../../containers/HeaderButton';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import ListItem from '../../containers/ListItem';
|
||||
import ItemInfo from '../../containers/ItemInfo';
|
||||
import { DisclosureImage } from '../../containers/DisclosureIndicator';
|
||||
import Separator from '../../containers/Separator';
|
||||
import * as List from '../../containers/List';
|
||||
import I18n from '../../i18n';
|
||||
import RocketChat, { CRASH_REPORT_KEY, ANALYTICS_EVENTS_KEY } from '../../lib/rocketchat';
|
||||
import {
|
||||
getReadableVersion, getDeviceModel, isAndroid
|
||||
} from '../../utils/deviceInfo';
|
||||
import openLink from '../../utils/openLink';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import { showErrorAlert, showConfirmationAlert } from '../../utils/info';
|
||||
import styles from './styles';
|
||||
import {
|
||||
loggerConfig, analytics, logEvent, events
|
||||
} from '../../utils/log';
|
||||
|
@ -44,22 +39,6 @@ import database from '../../lib/database';
|
|||
import { isFDroidBuild } from '../../constants/environment';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
|
||||
|
||||
const SectionSeparator = React.memo(({ theme }) => (
|
||||
<View
|
||||
style={[
|
||||
styles.sectionSeparatorBorder,
|
||||
{
|
||||
borderColor: themes[theme].separatorColor,
|
||||
backgroundColor: themes[theme].auxiliaryBackground
|
||||
}
|
||||
]}
|
||||
/>
|
||||
));
|
||||
SectionSeparator.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
class SettingsView extends React.Component {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }) => ({
|
||||
headerLeft: () => (isMasterDetail ? (
|
||||
|
@ -223,11 +202,6 @@ class SettingsView extends React.Component {
|
|||
openLink(LICENSE_LINK, theme);
|
||||
}
|
||||
|
||||
renderDisclosure = () => {
|
||||
const { theme } = this.props;
|
||||
return <DisclosureImage theme={theme} />;
|
||||
}
|
||||
|
||||
renderCrashReportSwitch = () => {
|
||||
const { allowCrashReport } = this.props;
|
||||
return (
|
||||
|
@ -253,170 +227,153 @@ class SettingsView extends React.Component {
|
|||
render() {
|
||||
const { server, isMasterDetail, theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='settings-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<ScrollView
|
||||
{...scrollPersistTaps}
|
||||
contentContainerStyle={styles.listPadding}
|
||||
showsVerticalScrollIndicator={false}
|
||||
testID='settings-view-list'
|
||||
>
|
||||
<SafeAreaView testID='settings-view'>
|
||||
<StatusBar />
|
||||
<List.Container testID='settings-view-list'>
|
||||
{isMasterDetail ? (
|
||||
<>
|
||||
<Separator theme={theme} />
|
||||
<SidebarView theme={theme} />
|
||||
<SectionSeparator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Profile')}
|
||||
onPress={() => this.navigateToScreen('ProfileView')}
|
||||
showActionIndicator
|
||||
testID='settings-profile'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<SidebarView />
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Profile'
|
||||
onPress={() => this.navigateToScreen('ProfileView')}
|
||||
showActionIndicator
|
||||
testID='settings-profile'
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Contact_us')}
|
||||
onPress={this.sendEmail}
|
||||
showActionIndicator
|
||||
testID='settings-view-contact'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Language')}
|
||||
onPress={() => this.navigateToScreen('LanguageView')}
|
||||
showActionIndicator
|
||||
testID='settings-view-language'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
{!isFDroidBuild ? (
|
||||
<>
|
||||
<ListItem
|
||||
title={I18n.t('Review_this_app')}
|
||||
showActionIndicator
|
||||
onPress={onReviewPress}
|
||||
testID='settings-view-review-app'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Share_this_app')}
|
||||
showActionIndicator
|
||||
onPress={this.shareApp}
|
||||
testID='settings-view-share-app'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Default_browser')}
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('DefaultBrowserView')}
|
||||
testID='settings-view-default-browser'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Theme')}
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('ThemeView')}
|
||||
testID='settings-view-theme'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Screen_lock')}
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('ScreenLockConfigView')}
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Contact_us'
|
||||
onPress={this.sendEmail}
|
||||
showActionIndicator
|
||||
testID='settings-view-contact'
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Language'
|
||||
onPress={() => this.navigateToScreen('LanguageView')}
|
||||
showActionIndicator
|
||||
testID='settings-view-language'
|
||||
/>
|
||||
<List.Separator />
|
||||
{!isFDroidBuild ? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Review_this_app'
|
||||
showActionIndicator
|
||||
onPress={onReviewPress}
|
||||
testID='settings-view-review-app'
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Share_this_app'
|
||||
showActionIndicator
|
||||
onPress={this.shareApp}
|
||||
testID='settings-view-share-app'
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Default_browser'
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('DefaultBrowserView')}
|
||||
testID='settings-view-default-browser'
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Theme'
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('ThemeView')}
|
||||
testID='settings-view-theme'
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Screen_lock'
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('ScreenLockConfigView')}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('License')}
|
||||
onPress={this.onPressLicense}
|
||||
showActionIndicator
|
||||
testID='settings-view-license'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Version_no', { version: getReadableVersion })}
|
||||
onPress={this.copyAppVersion}
|
||||
testID='settings-view-version'
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Server_version', { version: server.version })}
|
||||
onPress={this.copyServerVersion}
|
||||
subtitle={`${ server.server.split('//')[1] }`}
|
||||
testID='settings-view-server-version'
|
||||
theme={theme}
|
||||
/>
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='License'
|
||||
onPress={this.onPressLicense}
|
||||
showActionIndicator
|
||||
testID='settings-view-license'
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={I18n.t('Version_no', { version: getReadableVersion })}
|
||||
onPress={this.copyAppVersion}
|
||||
testID='settings-view-version'
|
||||
translateTitle={false}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={I18n.t('Server_version', { version: server.version })}
|
||||
onPress={this.copyServerVersion}
|
||||
subtitle={`${ server.server.split('//')[1] }`}
|
||||
testID='settings-view-server-version'
|
||||
translateTitle={false}
|
||||
translateSubtitle={false}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
|
||||
{!isFDroidBuild ? (
|
||||
<>
|
||||
<ListItem
|
||||
title={I18n.t('Log_analytics_events')}
|
||||
testID='settings-view-analytics-events'
|
||||
right={() => this.renderAnalyticsEventsSwitch()}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Send_crash_report')}
|
||||
testID='settings-view-crash-report'
|
||||
right={() => this.renderCrashReportSwitch()}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ItemInfo
|
||||
info={I18n.t('Crash_report_disclaimer')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Log_analytics_events'
|
||||
testID='settings-view-analytics-events'
|
||||
right={() => this.renderAnalyticsEventsSwitch()}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Send_crash_report'
|
||||
testID='settings-view-crash-report'
|
||||
right={() => this.renderCrashReportSwitch()}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='Crash_report_disclaimer' />
|
||||
</List.Section>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Clear_cache')}
|
||||
testID='settings-clear-cache'
|
||||
onPress={this.handleClearCache}
|
||||
right={this.renderDisclosure}
|
||||
color={themes[theme].dangerColor}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<ListItem
|
||||
title={I18n.t('Logout')}
|
||||
testID='settings-logout'
|
||||
onPress={this.handleLogout}
|
||||
right={this.renderDisclosure}
|
||||
color={themes[theme].dangerColor}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
</ScrollView>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Clear_cache'
|
||||
testID='settings-clear-cache'
|
||||
onPress={this.handleClearCache}
|
||||
showActionIndicator
|
||||
color={themes[theme].dangerColor}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Logout'
|
||||
testID='settings-logout'
|
||||
onPress={this.handleLogout}
|
||||
showActionIndicator
|
||||
color={themes[theme].dangerColor}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import sharedStyles from '../Styles';
|
||||
|
||||
export default StyleSheet.create({
|
||||
sectionSeparatorBorder: {
|
||||
...sharedStyles.separatorVertical,
|
||||
height: 36
|
||||
},
|
||||
listPadding: {
|
||||
paddingVertical: 36
|
||||
}
|
||||
});
|
|
@ -458,10 +458,9 @@ class ShareListView extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView>
|
||||
<StatusBar />
|
||||
{this.renderContent()}
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
|
|
@ -324,7 +324,6 @@ class ShareView extends Component {
|
|||
return (
|
||||
<SafeAreaView
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
theme={theme}
|
||||
>
|
||||
<StatusBar barStyle='light-content' backgroundColor={themes[theme].previewBackground} />
|
||||
{this.renderContent()}
|
||||
|
|
|
@ -215,7 +215,7 @@ class Sidebar extends Component {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<SafeAreaView testID='sidebar-view' style={{ backgroundColor: themes[theme].focusedBackground }} vertical={isMasterDetail} theme={theme}>
|
||||
<SafeAreaView testID='sidebar-view' style={{ backgroundColor: themes[theme].focusedBackground }} vertical={isMasterDetail}>
|
||||
<ScrollView
|
||||
style={[
|
||||
styles.container,
|
||||
|
|
|
@ -4,8 +4,7 @@ import { FlatList, StyleSheet } from 'react-native';
|
|||
import { connect } from 'react-redux';
|
||||
|
||||
import I18n from '../i18n';
|
||||
import Separator from '../containers/Separator';
|
||||
import ListItem from '../containers/ListItem';
|
||||
import * as List from '../containers/List';
|
||||
import Status from '../containers/Status/Status';
|
||||
import TextInput from '../containers/TextInput';
|
||||
import EventEmitter from '../utils/events';
|
||||
|
@ -14,7 +13,6 @@ import RocketChat from '../lib/rocketchat';
|
|||
import log, { logEvent, events } from '../utils/log';
|
||||
|
||||
import { LISTENER } from '../containers/Toast';
|
||||
import { themes } from '../constants/colors';
|
||||
import { withTheme } from '../theme';
|
||||
import { getUserSelector } from '../selectors/login';
|
||||
import { CustomHeaderButtons, Item, CancelModalButton } from '../containers/HeaderButton';
|
||||
|
@ -37,9 +35,6 @@ const STATUS = [{
|
|||
}];
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
status: {
|
||||
marginRight: 16
|
||||
},
|
||||
inputContainer: {
|
||||
marginTop: 32,
|
||||
marginBottom: 32
|
||||
|
@ -129,11 +124,6 @@ class StatusView extends React.Component {
|
|||
this.setState({ loading: false });
|
||||
}
|
||||
|
||||
renderSeparator = () => {
|
||||
const { theme } = this.props;
|
||||
return <Separator theme={theme} />;
|
||||
}
|
||||
|
||||
renderHeader = () => {
|
||||
const { statusText } = this.state;
|
||||
const { user, theme } = this.props;
|
||||
|
@ -157,18 +147,18 @@ class StatusView extends React.Component {
|
|||
placeholder={I18n.t('What_are_you_doing_right_now')}
|
||||
testID='status-view-input'
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<List.Separator />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => {
|
||||
const { statusText } = this.state;
|
||||
const { theme, user } = this.props;
|
||||
const { user } = this.props;
|
||||
const { id, name } = item;
|
||||
return (
|
||||
<ListItem
|
||||
title={I18n.t(name)}
|
||||
<List.Item
|
||||
title={name}
|
||||
onPress={async() => {
|
||||
logEvent(events[`STATUS_${ item.id.toUpperCase() }`]);
|
||||
if (user.status !== item.id) {
|
||||
|
@ -184,25 +174,22 @@ class StatusView extends React.Component {
|
|||
}
|
||||
}}
|
||||
testID={`status-view-${ id }`}
|
||||
left={() => <Status style={styles.status} size={12} status={item.id} />}
|
||||
theme={theme}
|
||||
left={() => <Status size={12} status={item.id} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { loading } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='status-view' theme={theme}>
|
||||
<SafeAreaView testID='status-view'>
|
||||
<FlatList
|
||||
data={STATUS}
|
||||
keyExtractor={item => item.id}
|
||||
contentContainerStyle={{ borderColor: themes[theme].separatorColor }}
|
||||
renderItem={this.renderItem}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
ListFooterComponent={() => <Separator theme={theme} />}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
ListFooterComponent={List.Separator}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
/>
|
||||
<Loading visible={loading} />
|
||||
</SafeAreaView>
|
||||
|
|
|
@ -121,11 +121,6 @@ export default StyleSheet.create({
|
|||
inputLastChild: {
|
||||
marginBottom: 15
|
||||
},
|
||||
listContentContainer: {
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
marginVertical: 36
|
||||
},
|
||||
notchLandscapeContainer: {
|
||||
marginTop: -34,
|
||||
paddingHorizontal: 30
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, Text, View, StyleSheet
|
||||
} from 'react-native';
|
||||
|
||||
import I18n from '../i18n';
|
||||
import { withTheme } from '../theme';
|
||||
import { themes } from '../constants/colors';
|
||||
import sharedStyles from './Styles';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import Separator from '../containers/Separator';
|
||||
import ListItem from '../containers/ListItem';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import * as List from '../containers/List';
|
||||
import { THEME_PREFERENCES_KEY } from '../lib/rocketchat';
|
||||
import { supportSystemTheme } from '../utils/deviceInfo';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
|
@ -39,8 +33,6 @@ const THEMES = [
|
|||
}, {
|
||||
label: 'Dark',
|
||||
value: 'dark',
|
||||
separator: true,
|
||||
header: 'Dark_level',
|
||||
group: DARK_GROUP
|
||||
}, {
|
||||
label: 'Black',
|
||||
|
@ -53,20 +45,8 @@ if (supportSystemTheme()) {
|
|||
THEMES.unshift(SYSTEM_THEME);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
list: {
|
||||
paddingBottom: 18
|
||||
},
|
||||
info: {
|
||||
paddingTop: 25,
|
||||
paddingBottom: 18,
|
||||
paddingHorizontal: 16
|
||||
},
|
||||
infoText: {
|
||||
fontSize: 16,
|
||||
...sharedStyles.textRegular
|
||||
}
|
||||
});
|
||||
const themeGroup = THEMES.filter(item => item.group === THEME_GROUP);
|
||||
const darkGroup = THEMES.filter(item => item.group === DARK_GROUP);
|
||||
|
||||
class ThemeView extends React.Component {
|
||||
static navigationOptions = () => ({
|
||||
|
@ -114,74 +94,44 @@ class ThemeView extends React.Component {
|
|||
await UserPreferences.setMapAsync(THEME_PREFERENCES_KEY, newTheme);
|
||||
};
|
||||
|
||||
renderSeparator = () => {
|
||||
const { theme } = this.props;
|
||||
return <Separator theme={theme} />;
|
||||
}
|
||||
|
||||
renderIcon = () => {
|
||||
const { theme } = this.props;
|
||||
return <CustomIcon name='check' size={20} color={themes[theme].tintColor} />;
|
||||
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
||||
}
|
||||
|
||||
renderItem = ({ item, index }) => {
|
||||
const { theme } = this.props;
|
||||
renderItem = ({ item }) => {
|
||||
const { label, value } = item;
|
||||
const isFirst = index === 0;
|
||||
return (
|
||||
<>
|
||||
{item.separator || isFirst ? this.renderSectionHeader(item.header) : null}
|
||||
<ListItem
|
||||
title={I18n.t(label)}
|
||||
<List.Item
|
||||
title={label}
|
||||
onPress={() => this.onClick(item)}
|
||||
testID={`theme-view-${ value }`}
|
||||
right={this.isSelected(item) ? this.renderIcon : null}
|
||||
theme={theme}
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
renderSectionHeader = (header = 'Theme') => {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<>
|
||||
<View style={styles.info}>
|
||||
<Text style={[styles.infoText, { color: themes[theme].infoText }]}>{I18n.t(header)}</Text>
|
||||
</View>
|
||||
{this.renderSeparator()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
renderFooter = () => {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<View style={[styles.info, sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]}>
|
||||
<Text style={{ color: themes[theme].infoText }}>
|
||||
{I18n.t('Applying_a_theme_will_change_how_the_app_looks')}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='theme-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<FlatList
|
||||
data={THEMES}
|
||||
keyExtractor={item => item.value + item.group}
|
||||
contentContainerStyle={[
|
||||
styles.list,
|
||||
{ borderColor: themes[theme].separatorColor }
|
||||
]}
|
||||
renderItem={this.renderItem}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
ListFooterComponent={this.renderFooter}
|
||||
ItemSeparatorComponent={this.renderSeparator}
|
||||
/>
|
||||
<SafeAreaView testID='theme-view'>
|
||||
<StatusBar />
|
||||
<List.Container>
|
||||
<List.Section title='Theme'>
|
||||
<List.Separator />
|
||||
{
|
||||
themeGroup.map(item => this.renderItem({ item }))
|
||||
}
|
||||
</List.Section>
|
||||
<List.Section title='Dark_level'>
|
||||
<List.Separator />
|
||||
{
|
||||
darkGroup.map(item => this.renderItem({ item }))
|
||||
}
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -334,8 +334,8 @@ class ThreadMessagesView extends React.Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView testID='thread-messages-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<SafeAreaView testID='thread-messages-view'>
|
||||
<StatusBar />
|
||||
<FlatList
|
||||
data={messages}
|
||||
extraData={this.state}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Text
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const Info = React.memo(({ info, theme }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.infoText,
|
||||
{
|
||||
color: themes[theme].infoText,
|
||||
backgroundColor: themes[theme].auxiliaryBackground
|
||||
}
|
||||
]}
|
||||
>
|
||||
{info}
|
||||
</Text>
|
||||
));
|
||||
|
||||
Info.propTypes = {
|
||||
info: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default Info;
|
|
@ -1,23 +0,0 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
View
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const SectionSeparator = React.memo(({ theme }) => (
|
||||
<View
|
||||
style={[
|
||||
styles.sectionSeparatorBorder,
|
||||
{ backgroundColor: themes[theme].auxiliaryBackground }
|
||||
]}
|
||||
/>
|
||||
));
|
||||
|
||||
SectionSeparator.propTypes = {
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default SectionSeparator;
|
|
@ -1,29 +0,0 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Text
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const SectionTitle = React.memo(({ title, theme }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.sectionTitle,
|
||||
{
|
||||
backgroundColor: themes[theme].auxiliaryBackground,
|
||||
color: themes[theme].infoText
|
||||
}
|
||||
]}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
));
|
||||
|
||||
SectionTitle.propTypes = {
|
||||
title: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default SectionTitle;
|
|
@ -1,27 +1,26 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
View, ScrollView, Text
|
||||
} from 'react-native';
|
||||
import { Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { themes } from '../../constants/colors';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import ListItem from '../../containers/ListItem';
|
||||
import Separator from '../../containers/Separator';
|
||||
import * as List from '../../containers/List';
|
||||
import I18n from '../../i18n';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import styles from './styles';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import { withTheme } from '../../theme';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import SectionTitle from './SectionTitle';
|
||||
import SectionSeparator from './SectionSeparator';
|
||||
import Info from './Info';
|
||||
import { OPTIONS } from './options';
|
||||
import ActivityIndicator from '../../containers/ActivityIndicator';
|
||||
import { DisclosureImage } from '../../containers/DisclosureIndicator';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import sharedStyles from '../Styles';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
pickerText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 16
|
||||
}
|
||||
});
|
||||
|
||||
class UserNotificationPreferencesView extends React.Component {
|
||||
static navigationOptions = () => ({
|
||||
|
@ -30,7 +29,6 @@ class UserNotificationPreferencesView extends React.Component {
|
|||
|
||||
static propTypes = {
|
||||
navigation: PropTypes.object,
|
||||
route: PropTypes.object,
|
||||
theme: PropTypes.string,
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.string
|
||||
|
@ -90,72 +88,55 @@ class UserNotificationPreferencesView extends React.Component {
|
|||
this.setState({ preferences: settings.preferences });
|
||||
}
|
||||
|
||||
renderDisclosure = () => {
|
||||
const { theme } = this.props;
|
||||
return <DisclosureImage theme={theme} />;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
const { loading } = this.state;
|
||||
return (
|
||||
<SafeAreaView testID='user-notification-preference-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<ScrollView
|
||||
{...scrollPersistTaps}
|
||||
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
testID='user-notification-preference-view-list'
|
||||
>
|
||||
<SafeAreaView testID='user-notification-preference-view'>
|
||||
<StatusBar />
|
||||
<List.Container>
|
||||
{loading
|
||||
? (
|
||||
<>
|
||||
<SectionSeparator theme={theme} />
|
||||
<SectionTitle title={I18n.t('DESKTOP_NOTIFICATIONS')} theme={theme} />
|
||||
<List.Section title='Desktop_Notifications'>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Alert'
|
||||
testID='user-notification-preference-view-alert'
|
||||
onPress={title => this.pickerSelection(title, 'desktopNotifications')}
|
||||
right={() => this.renderPickerOption('desktopNotifications')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='Desktop_Alert_info' />
|
||||
</List.Section>
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Alert')}
|
||||
testID='user-notification-preference-view-alert'
|
||||
onPress={title => this.pickerSelection(title, 'desktopNotifications')}
|
||||
right={() => this.renderPickerOption('desktopNotifications')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('Desktop_Alert_info')} theme={theme} />
|
||||
<List.Section title='Push_Notifications'>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Alert'
|
||||
testID='user-notification-preference-view-push-notification'
|
||||
onPress={title => this.pickerSelection(title, 'mobileNotifications')}
|
||||
right={() => this.renderPickerOption('mobileNotifications')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='Push_Notifications_Alert_Info' />
|
||||
</List.Section>
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<SectionTitle title={I18n.t('PUSH_NOTIFICATIONS')} theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Alert')}
|
||||
testID='user-notification-preference-view-push-notification'
|
||||
onPress={title => this.pickerSelection(title, 'mobileNotifications')}
|
||||
right={() => this.renderPickerOption('mobileNotifications')}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('Push_Notifications_Alert_Info')} theme={theme} />
|
||||
|
||||
<SectionSeparator theme={theme} />
|
||||
<SectionTitle title={I18n.t('EMAIL')} theme={theme} />
|
||||
<Separator theme={theme} />
|
||||
|
||||
<ListItem
|
||||
title={I18n.t('Alert')}
|
||||
testID='user-notification-preference-view-email-alert'
|
||||
onPress={title => this.pickerSelection(title, 'emailNotificationMode')}
|
||||
right={() => this.renderPickerOption('emailNotificationMode')}
|
||||
theme={theme}
|
||||
/>
|
||||
|
||||
<Separator theme={theme} />
|
||||
<Info info={I18n.t('You_need_to_verifiy_your_email_address_to_get_notications')} theme={theme} />
|
||||
<List.Section title='Email'>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Alert'
|
||||
testID='user-notification-preference-view-email-alert'
|
||||
onPress={title => this.pickerSelection(title, 'emailNotificationMode')}
|
||||
right={() => this.renderPickerOption('emailNotificationMode')}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Info info='You_need_to_verifiy_your_email_address_to_get_notications' />
|
||||
</List.Section>
|
||||
</>
|
||||
) : <ActivityIndicator theme={theme} />
|
||||
}
|
||||
<View style={[styles.marginBottom, { backgroundColor: themes[theme].auxiliaryBackground }]} />
|
||||
</ScrollView>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import sharedStyles from '../Styles';
|
||||
|
||||
export default StyleSheet.create({
|
||||
sectionSeparatorBorder: {
|
||||
height: 10
|
||||
},
|
||||
marginBottom: {
|
||||
height: 30
|
||||
},
|
||||
contentContainer: {
|
||||
marginVertical: 10
|
||||
},
|
||||
infoText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 13,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10
|
||||
},
|
||||
sectionTitle: {
|
||||
...sharedStyles.separatorBottom,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 10,
|
||||
fontSize: 14
|
||||
},
|
||||
pickerText: {
|
||||
...sharedStyles.textRegular,
|
||||
fontSize: 16
|
||||
}
|
||||
});
|
|
@ -1,18 +1,13 @@
|
|||
import React from 'react';
|
||||
import { ScrollView } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import I18n from '../../i18n';
|
||||
import {
|
||||
logEvent, events
|
||||
} from '../../utils/log';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import Separator from '../../containers/Separator';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import ListItem from '../../containers/ListItem';
|
||||
import { DisclosureImage } from '../../containers/DisclosureIndicator';
|
||||
import { withTheme } from '../../theme';
|
||||
import * as List from '../../containers/List';
|
||||
|
||||
class UserPreferencesView extends React.Component {
|
||||
static navigationOptions = () => ({
|
||||
|
@ -20,13 +15,7 @@ class UserPreferencesView extends React.Component {
|
|||
});
|
||||
|
||||
static propTypes = {
|
||||
navigation: PropTypes.object,
|
||||
theme: PropTypes.string
|
||||
}
|
||||
|
||||
renderDisclosure = () => {
|
||||
const { theme } = this.props;
|
||||
return <DisclosureImage theme={theme} />;
|
||||
navigation: PropTypes.object
|
||||
}
|
||||
|
||||
navigateToScreen = (screen, params) => {
|
||||
|
@ -36,30 +25,24 @@ class UserPreferencesView extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<SafeAreaView testID='preferences-view' theme={theme}>
|
||||
<StatusBar theme={theme} />
|
||||
<ScrollView
|
||||
{...scrollPersistTaps}
|
||||
contentContainerStyle={{ paddingVertical: 36 }}
|
||||
showsVerticalScrollIndicator={false}
|
||||
testID='preferences-view-list'
|
||||
>
|
||||
<ListItem
|
||||
title={I18n.t('Notifications')}
|
||||
onPress={() => this.navigateToScreen('UserNotificationPrefView')}
|
||||
showActionIndicator
|
||||
testID='preferences-view-notifications'
|
||||
right={this.renderDisclosure}
|
||||
theme={theme}
|
||||
/>
|
||||
<Separator theme={theme} />
|
||||
</ScrollView>
|
||||
<SafeAreaView testID='preferences-view'>
|
||||
<StatusBar />
|
||||
<List.Container>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={I18n.t('Notifications')}
|
||||
onPress={() => this.navigateToScreen('UserNotificationPrefView')}
|
||||
showActionIndicator
|
||||
testID='preferences-view-notifications'
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UserPreferencesView);
|
||||
export default UserPreferencesView;
|
||||
|
|
|
@ -5,12 +5,12 @@ import PropTypes from 'prop-types';
|
|||
import { withTheme } from '../theme';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import { themes } from '../constants/colors';
|
||||
import Separator from '../containers/Separator';
|
||||
import openLink from '../utils/openLink';
|
||||
import I18n from '../i18n';
|
||||
import debounce from '../utils/debounce';
|
||||
import sharedStyles from './Styles';
|
||||
import ListItem from '../containers/ListItem';
|
||||
import * as List from '../containers/List';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
noResult: {
|
||||
|
@ -18,23 +18,18 @@ const styles = StyleSheet.create({
|
|||
paddingVertical: 56,
|
||||
...sharedStyles.textAlignCenter,
|
||||
...sharedStyles.textSemibold
|
||||
},
|
||||
withoutBorder: {
|
||||
borderBottomWidth: 0,
|
||||
borderTopWidth: 0
|
||||
}
|
||||
});
|
||||
|
||||
const Item = ({ item, theme }) => (
|
||||
<ListItem
|
||||
const Item = ({ item }) => (
|
||||
<List.Item
|
||||
title={item.navigation?.page?.title || I18n.t('Empty_title')}
|
||||
onPress={() => openLink(item.navigation?.page?.location?.href)}
|
||||
theme={theme}
|
||||
translateTitle={false}
|
||||
/>
|
||||
);
|
||||
Item.propTypes = {
|
||||
item: PropTypes.object,
|
||||
theme: PropTypes.string
|
||||
item: PropTypes.object
|
||||
};
|
||||
|
||||
const VisitorNavigationView = ({ route, theme }) => {
|
||||
|
@ -67,24 +62,20 @@ const VisitorNavigationView = ({ route, theme }) => {
|
|||
}, 300);
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
data={pages}
|
||||
renderItem={({ item }) => <Item item={item} theme={theme} />}
|
||||
ItemSeparatorComponent={() => <Separator theme={theme} />}
|
||||
contentContainerStyle={[
|
||||
sharedStyles.listContentContainer,
|
||||
{
|
||||
backgroundColor: themes[theme].auxiliaryBackground,
|
||||
borderColor: themes[theme].separatorColor
|
||||
},
|
||||
!pages.length && styles.withoutBorder
|
||||
]}
|
||||
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
|
||||
ListEmptyComponent={() => <Text style={[styles.noResult, { color: themes[theme].titleText }]}>{I18n.t('No_results_found')}</Text>}
|
||||
keyExtractor={item => item}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={5}
|
||||
/>
|
||||
<SafeAreaView>
|
||||
<FlatList
|
||||
data={pages}
|
||||
renderItem={({ item }) => <Item item={item} theme={theme} />}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
ListFooterComponent={List.Separator}
|
||||
ListHeaderComponent={List.Separator}
|
||||
contentContainerStyle={List.styles.contentContainerStyleFlatList}
|
||||
ListEmptyComponent={() => <Text style={[styles.noResult, { color: themes[theme].titleText }]}>{I18n.t('No_results_found')}</Text>}
|
||||
keyExtractor={item => item}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={5}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
VisitorNavigationView.propTypes = {
|
||||
|
|
|
@ -37,7 +37,7 @@ describe('Status screen', () => {
|
|||
describe('Usage', async () => {
|
||||
it('should change status', async () => {
|
||||
await element(by.id('status-view-busy')).tap();
|
||||
await expect(element(by.id('status-view-current-busy'))).toExist();
|
||||
await waitFor(element(by.id('status-view-current-busy'))).toExist().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should change status text', async () => {
|
||||
|
|
|
@ -15,7 +15,7 @@ async function navigateToRoomInfo(type) {
|
|||
}
|
||||
await searchRoom(room);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
|
||||
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
|
||||
await element(by.id(`rooms-list-view-item-${ room }`)).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
|
||||
await element(by.id('room-view-header-actions')).tap();
|
||||
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
||||
|
|
|
@ -5,7 +5,7 @@ import RNBootSplash from 'react-native-bootsplash';
|
|||
import 'react-native-gesture-handler';
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => jest.fn(() => null));
|
||||
// jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => jest.fn(() => null));
|
||||
|
||||
RNBootSplash.hide();
|
||||
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions, react/prop-types */
|
||||
import React from 'react';
|
||||
import { FlatList } from 'react-native';
|
||||
import { storiesOf } from '@storybook/react-native';
|
||||
|
||||
import * as List from '../../app/containers/List';
|
||||
import SafeAreaView from '../../app/containers/SafeAreaView';
|
||||
import { longText } from '../utils';
|
||||
import { ThemeContext } from '../../app/theme';
|
||||
import { DimensionsContext } from '../../app/dimensions';
|
||||
|
||||
const stories = storiesOf('List', module);
|
||||
|
||||
stories.add('title and subtitle', () => (
|
||||
<List.Container>
|
||||
<List.Separator />
|
||||
<List.Item title='Chats' />
|
||||
<List.Separator />
|
||||
<List.Item title='Chats' subtitle='All' />
|
||||
<List.Separator />
|
||||
<List.Item title={longText} subtitle={longText} translateTitle={false} translateSubtitle={false} testID='test-id' />
|
||||
<List.Separator />
|
||||
</List.Container>
|
||||
));
|
||||
|
||||
stories.add('pressable', () => (
|
||||
<List.Container>
|
||||
<List.Separator />
|
||||
<List.Item title='Press me' onPress={() => alert('Hi there!')} translateTitle={false} />
|
||||
<List.Separator />
|
||||
<List.Item title={'I\'m disabled'} onPress={() => alert('Hi there!')} disabled translateTitle={false} />
|
||||
<List.Separator />
|
||||
</List.Container>
|
||||
));
|
||||
|
||||
|
||||
stories.add('header', () => (
|
||||
<List.Container>
|
||||
<List.Header title='Chats' />
|
||||
<List.Header title={longText} translateTitle={false} />
|
||||
</List.Container>
|
||||
));
|
||||
|
||||
stories.add('icon', () => (
|
||||
<List.Container>
|
||||
<List.Icon name='emoji' />
|
||||
</List.Container>
|
||||
));
|
||||
|
||||
stories.add('separator', () => (
|
||||
<List.Container>
|
||||
<List.Separator />
|
||||
</List.Container>
|
||||
));
|
||||
|
||||
stories.add('with section and info', () => (
|
||||
<SafeAreaView>
|
||||
<List.Container>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
<List.Section title='Chats'>
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
<List.Info info='Chats' />
|
||||
</List.Section>
|
||||
<List.Section title={longText} translateTitle={false}>
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
<List.Item title='Section Item' translateTitle={false} />
|
||||
<List.Separator />
|
||||
<List.Info info={longText} translateInfo={false} />
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
));
|
||||
|
||||
stories.add('with icon', () => (
|
||||
<List.Container>
|
||||
<List.Separator />
|
||||
<List.Item title='Icon Left' translateTitle={false} left={() => <List.Icon name='emoji' />} />
|
||||
<List.Separator />
|
||||
<List.Item title='Icon Right' translateTitle={false} right={() => <List.Icon name='emoji' />} />
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={longText}
|
||||
subtitle={longText}
|
||||
translateTitle={false}
|
||||
translateSubtitle={false}
|
||||
left={() => <List.Icon name='emoji' />}
|
||||
right={() => <List.Icon name='emoji' />}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item title='Show Action Indicator' translateTitle={false} showActionIndicator />
|
||||
<List.Separator />
|
||||
</List.Container>
|
||||
));
|
||||
|
||||
stories.add('with custom color', () => (
|
||||
<List.Container>
|
||||
<List.Separator />
|
||||
<List.Item title='Chats' color='red' />
|
||||
<List.Separator />
|
||||
</List.Container>
|
||||
));
|
||||
|
||||
const ListItemFull = ({ ...props }) => (
|
||||
<List.Item
|
||||
title='Chats'
|
||||
subtitle='All'
|
||||
onPress={() => alert('Hi')}
|
||||
left={() => <List.Icon name='emoji' />}
|
||||
right={() => <List.Icon name='emoji' />}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
const ListFull = () => (
|
||||
<SafeAreaView>
|
||||
<List.Container>
|
||||
<List.Section title='Chats'>
|
||||
<List.Separator />
|
||||
<ListItemFull />
|
||||
<List.Separator />
|
||||
<ListItemFull disabled />
|
||||
<List.Separator />
|
||||
<List.Info info='Chats' />
|
||||
</List.Section>
|
||||
<List.Section title='Chats'>
|
||||
<List.Separator />
|
||||
<ListItemFull />
|
||||
<List.Separator />
|
||||
<ListItemFull disabled />
|
||||
<List.Separator />
|
||||
<List.Info info='Chats' />
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
||||
const ThemeStory = ({ theme }) => (
|
||||
<ThemeContext.Provider
|
||||
value={{ theme }}
|
||||
>
|
||||
<ListFull />
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
|
||||
stories.add('with dark theme', () => <ThemeStory theme='dark' />);
|
||||
|
||||
stories.add('with black theme', () => <ThemeStory theme='black' />);
|
||||
|
||||
const FontStory = ({ fontScale }) => (
|
||||
<DimensionsContext.Provider
|
||||
value={{ fontScale }}
|
||||
>
|
||||
<ListFull />
|
||||
</DimensionsContext.Provider>
|
||||
);
|
||||
|
||||
/**
|
||||
* It's going to test height only.
|
||||
* Font scale on text and icons is applied based on OS setting
|
||||
*/
|
||||
stories.add('with small font', () => <FontStory fontScale={0.8} />);
|
||||
|
||||
stories.add('with bigger font', () => <FontStory fontScale={1.5} />);
|
||||
|
||||
stories.add('with FlatList', () => (
|
||||
<SafeAreaView>
|
||||
<FlatList
|
||||
data={[...Array(30).keys()]}
|
||||
contentContainerStyle={List.styles.contentContainerStyleFlatList}
|
||||
renderItem={({ item }) => <List.Item title={item} translateTitle={false} />}
|
||||
ListHeaderComponent={List.Separator}
|
||||
ListFooterComponent={List.Separator}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
keyExtractor={item => item}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
));
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue