Skip to content

Commit

Permalink
Merge branch 'develop' into new.teams
Browse files Browse the repository at this point in the history
# Conflicts:
#	app/containers/RoomTypeIcon.js
#	app/i18n/locales/en.js
#	app/presentation/RoomItem/RoomItem.js
#	app/presentation/RoomItem/TypeIcon.js
#	app/views/RoomActionsView/index.js
#	app/views/RoomInfoView/index.js
#	app/views/RoomView/Header/Header.js
#	app/views/RoomView/Header/Icon.js
#	app/views/RoomView/Header/index.js
  • Loading branch information
diegolmello committed Apr 5, 2021
2 parents a6459e4 + 5a96f1f commit e845a1a
Show file tree
Hide file tree
Showing 89 changed files with 11,193 additions and 8,888 deletions.
2,343 changes: 1,835 additions & 508 deletions __tests__/__snapshots__/Storyshots.test.js.snap

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode VERSIONCODE as Integer
versionName "4.15.0"
versionName "4.16.0"
vectorDrawables.useSupportLibrary = true
if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
Expand Down
Binary file modified android/app/src/main/assets/fonts/custom.ttf
Binary file not shown.
3 changes: 2 additions & 1 deletion app/constants/colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ export const STATUS_COLORS = {
online: '#2de0a5',
busy: '#f5455c',
away: '#ffd21f',
offline: '#cbced1'
offline: '#cbced1',
loading: '#9ea2a8'
};

export const SWITCH_TRACK_COLOR = {
Expand Down
2 changes: 1 addition & 1 deletion app/containers/Header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const getHeaderHeight = (isLandscape) => {

export const getHeaderTitlePosition = ({ insets, numIconsRight }) => ({
left: insets.left + 60,
right: insets.right + (45 * numIconsRight)
right: insets.right + Math.max(45 * numIconsRight, 15)
});

const styles = StyleSheet.create({
Expand Down
21 changes: 14 additions & 7 deletions app/containers/RoomTypeIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { CustomIcon } from '../lib/Icons';
import { STATUS_COLORS, themes } from '../constants/colors';
import Status from './Status/Status';
import { withTheme } from '../theme';

const styles = StyleSheet.create({
icon: {
marginRight: 2
marginRight: 4
}
});

Expand All @@ -18,6 +20,15 @@ const RoomTypeIcon = React.memo(({
}

const color = themes[theme].titleText;
const iconStyle = [
styles.icon,
{ color },
style
];

if (type === 'd' && !isGroupChat) {
return <Status style={[iconStyle, { color: STATUS_COLORS[status] ?? STATUS_COLORS.offline }]} size={size} status={status} />;
}

let icon = 'channel-private';
if (teamMain) {
Expand All @@ -40,11 +51,7 @@ const RoomTypeIcon = React.memo(({
<CustomIcon
name={icon}
size={size}
style={[
type === 'l' && status ? { color: STATUS_COLORS[status] } : { color },
styles.icon,
style
]}
style={iconStyle}
/>
);
});
Expand All @@ -63,4 +70,4 @@ RoomTypeIcon.defaultProps = {
size: 16
};

export default RoomTypeIcon;
export default withTheme(RoomTypeIcon);
47 changes: 24 additions & 23 deletions app/containers/Status/Status.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import { STATUS_COLORS, themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons';
import { STATUS_COLORS } from '../../constants/colors';

const Status = React.memo(({
status, size, style, theme, ...props
}) => (
<View
style={
[
style,
{
borderRadius: size,
width: size,
height: size,
backgroundColor: STATUS_COLORS[status] ?? STATUS_COLORS.offline,
borderColor: themes[theme].backgroundColor
}
]}
{...props}
/>
));
status, size, style, ...props
}) => {
const name = `status-${ status }`;
const isNameValid = CustomIcon.hasIcon(name);
const iconName = isNameValid ? name : 'status-offline';
const calculatedStyle = [{
width: size, height: size, textAlignVertical: 'center'
}, style];

return (
<CustomIcon
style={calculatedStyle}
size={size}
name={iconName}
color={STATUS_COLORS[status] ?? STATUS_COLORS.offline}
{...props}
/>
);
});

Status.propTypes = {
status: PropTypes.string,
size: PropTypes.number,
style: PropTypes.any,
theme: PropTypes.string
style: PropTypes.any
};
Status.defaultProps = {
status: 'offline',
size: 16,
theme: 'light'
size: 32
};

export default Status;
31 changes: 9 additions & 22 deletions app/containers/Status/index.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
import React from 'react';
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import Status from './Status';
import { withTheme } from '../../theme';

class StatusContainer extends React.PureComponent {
static propTypes = {
style: PropTypes.any,
size: PropTypes.number,
status: PropTypes.string,
theme: PropTypes.string
};
const StatusContainer = memo(({ style, size = 32, status }) => <Status size={size} style={style} status={status} />);

static defaultProps = {
size: 16
}

render() {
const {
style, size, status, theme
} = this.props;
return <Status size={size} style={style} status={status} theme={theme} />;
}
}
StatusContainer.propTypes = {
style: PropTypes.any,
size: PropTypes.number,
status: PropTypes.string
};

const mapStateToProps = (state, ownProps) => ({
status: state.meteor.connected ? (state.activeUsers[ownProps.id] && state.activeUsers[ownProps.id].status) : 'offline'
status: state.meteor.connected ? (state.activeUsers[ownProps.id] && state.activeUsers[ownProps.id].status) : 'loading'
});

export default connect(mapStateToProps)(withTheme(StatusContainer));
export default connect(mapStateToProps)(StatusContainer);
2 changes: 1 addition & 1 deletion app/containers/markdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ class Markdown extends PureComponent {

// Ex: '[ ](https://open.rocket.chat/group/test?msg=abcdef) Test'
// Return: 'Test'
m = m.replace(/^\[([\s]]*)\]\(([^)]*)\)\s/, '').trim();
m = m.replace(/^\[([\s]*)\]\(([^)]*)\)\s/, '').trim();

if (preview) {
m = shortnameToUnicode(m);
Expand Down
15 changes: 12 additions & 3 deletions app/containers/message/Reply.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const Title = React.memo(({ attachment, timeFormat, theme }) => {
if (!attachment.author_name) {
return null;
}
const time = attachment.ts ? moment(attachment.ts).format(timeFormat) : null;
const time = attachment.message_link && attachment.ts ? moment(attachment.ts).format(timeFormat) : null;
return (
<View style={styles.authorContainer}>
{attachment.author_name ? <Text style={[styles.author, { color: themes[theme].bodyText }]}>{attachment.author_name}</Text> : null}
Expand Down Expand Up @@ -158,6 +158,16 @@ const Reply = React.memo(({
openLink(url, theme);
};

let { borderColor, chatComponentBackground: backgroundColor } = themes[theme];
try {
if (attachment.color) {
backgroundColor = transparentize(attachment.color, 0.80);
borderColor = attachment.color;
}
} catch (e) {
// fallback to default
}

return (
<>
<Touchable
Expand All @@ -167,8 +177,7 @@ const Reply = React.memo(({
index > 0 && styles.marginTop,
attachment.description && styles.marginBottom,
{
backgroundColor: attachment.color ? transparentize(attachment.color, 0.80) : themes[theme].chatComponentBackground,
borderColor: attachment.color || themes[theme].borderColor
backgroundColor, borderColor
}
]}
background={Touchable.Ripple(themes[theme].bannerBackground)}
Expand Down
64 changes: 41 additions & 23 deletions app/i18n/index.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,71 @@
import i18n from 'i18n-js';
import { I18nManager } from 'react-native';
import * as RNLocalize from 'react-native-localize';
import moment from 'moment';
import 'moment/min/locales';

export * from './isRTL';
import { toMomentLocale } from '../utils/moment';
import { isRTL } from './isRTL';

export { isRTL };

export const LANGUAGES = [
{
label: 'English',
value: 'en',
file: require('./locales/en').default
file: () => require('./locales/en.json')
}, {
label: '简体中文',
value: 'zh-CN',
file: require('./locales/zh-CN').default
file: () => require('./locales/zh-CN.json')
}, {
label: '繁體中文',
value: 'zh-TW',
file: require('./locales/zh-TW').default
file: () => require('./locales/zh-TW.json')
}, {
label: 'Deutsch',
value: 'de',
file: require('./locales/de').default
file: () => require('./locales/de.json')
}, {
label: 'Español (ES)',
value: 'es-ES',
file: require('./locales/es-ES').default
file: () => require('./locales/es-ES.json')
}, {
label: 'Français',
value: 'fr',
file: require('./locales/fr').default
file: () => require('./locales/fr.json')
}, {
label: 'Português (BR)',
value: 'pt-BR',
file: require('./locales/pt-BR').default
file: () => require('./locales/pt-BR.json')
}, {
label: 'Português (PT)',
value: 'pt-PT',
file: require('./locales/pt-PT').default
file: () => require('./locales/pt-PT.json')
}, {
label: 'Russian',
value: 'ru',
file: require('./locales/ru').default
file: () => require('./locales/ru.json')
}, {
label: 'Nederlands',
value: 'nl',
file: require('./locales/nl').default
file: () => require('./locales/nl.json')
}, {
label: 'Italiano',
value: 'it',
file: require('./locales/it').default
file: () => require('./locales/it.json')
}, {
label: '日本語',
value: 'ja',
file: require('./locales/ja').default
file: () => require('./locales/ja.json')
}, {
label: 'العربية',
value: 'ar',
file: require('./locales/ar').default
file: () => require('./locales/ar.json')
}, {
label: 'Türkçe',
value: 'tr',
file: require('./locales/tr').default
file: () => require('./locales/tr.json')
}
];

Expand All @@ -69,16 +74,29 @@ const translations = LANGUAGES.reduce((ret, item) => {
return ret;
}, {});

i18n.translations = translations;
i18n.fallbacks = true;
export const setLanguage = (l) => {
if (!l) {
return;
}
// server uses lowercase pattern (pt-br), but we're forced to use standard pattern (pt-BR)
const locale = LANGUAGES.find(ll => ll.value.toLowerCase() === l.toLowerCase())?.value;
// don't go forward if it's the same language and default language (en) was setup already
if (i18n.locale === locale && i18n.translations?.en) {
return;
}
i18n.locale = locale;
i18n.translations = { ...i18n.translations, [locale]: translations[locale]() };
I18nManager.forceRTL(isRTL(locale));
I18nManager.swapLeftAndRightInRTL(isRTL(locale));
i18n.isRTL = I18nManager.isRTL;
moment.locale(toMomentLocale(locale));
};

const defaultLanguage = { languageTag: 'en', isRTL: false };
const availableLanguages = Object.keys(i18n.translations);
const { languageTag, isRTL } = RNLocalize.findBestAvailableLanguage(availableLanguages) || defaultLanguage;
const availableLanguages = Object.keys(translations);
const { languageTag } = RNLocalize.findBestAvailableLanguage(availableLanguages) || defaultLanguage;

I18nManager.forceRTL(isRTL);
I18nManager.swapLeftAndRightInRTL(isRTL);
i18n.locale = languageTag;
i18n.isRTL = I18nManager.isRTL;
setLanguage(languageTag);
i18n.fallbacks = true;

export default i18n;
Loading

0 comments on commit e845a1a

Please sign in to comment.