Unverified Commit f5b013f4 authored by Diego Mello's avatar Diego Mello Committed by GitHub
Browse files

Merge 4.15.0 into master (#2984)



* [FIX] MessagesView title not working (#2294)

* Set title in header of room actions view items
Signed-off-by: default avatarEzequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Remove unneeded spaces
Signed-off-by: default avatarEzequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Set header title on constructor
Signed-off-by: default avatarEzequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

* Remove unused navigation options
Signed-off-by: default avatarEzequiel De Oliveira <ezequiel1de1oliveira@gmail.com>
Co-authored-by: default avatarDiego Mello <diegolmello@gmail.com>

* [TESTS] Stabilise Room Actions test (#2333)

* Stabilise Room Actions test

* Fix Create Room test

* Be more tolerant of slow starting apps in CI

* Be more tolerant of slow running apps in CI

* Switch visibility checks ti stabilise Room Create test in CI

* Move slow simulator readiness waiting to initial navigateToX methods rather than repeatedly in tests without description of purpose

* [CHORE] Update icon names (...
parent 197b78e8
......@@ -237,9 +237,13 @@ commands:
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY_OFFICIAL" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./NotificationService/Info.plist
else
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./NotificationService/Info.plist
fi
if [[ $APP_STORE_CONNECT_API_KEY ]]; then
......@@ -416,9 +420,13 @@ workflows:
- lint-testunit
# iOS Experimental
- ios-hold-build-experimental:
type: approval
requires:
- lint-testunit
- ios-build-experimental:
requires:
- lint-testunit
- ios-hold-build-experimental
- ios-hold-testflight-experimental:
type: approval
requires:
......@@ -444,9 +452,13 @@ workflows:
- ios-hold-testflight-official
# Android Experimental
- android-hold-build-experimental:
type: approval
requires:
- lint-testunit
- android-build-experimental:
requires:
- lint-testunit
- android-hold-build-experimental
- android-hold-google-play-beta-experimental:
type: approval
requires:
......
......@@ -6,7 +6,7 @@ module.exports = {
}
}
},
"parser": "babel-eslint",
"parser": "@babel/eslint-parser",
"extends": "airbnb",
"parserOptions": {
"sourceType": "module",
......@@ -21,7 +21,8 @@ module.exports = {
"react",
"jsx-a11y",
"import",
"react-native"
"react-native",
"@babel"
],
"env": {
"browser": true,
......@@ -148,7 +149,8 @@ module.exports = {
"react/jsx-curly-newline": [0],
"react/state-in-constructor": [0],
"no-async-promise-executor": [0],
"max-classes-per-file": [0]
"max-classes-per-file": [0],
"no-multiple-empty-lines": [0]
},
"globals": {
"__DEV__": true
......
......@@ -44404,6 +44404,309 @@ exports[`Storyshots Message list message 1`] = `
</View>
</View>
</View>
<Text
style={
Array [
Object {
"fontSize": 20,
"fontWeight": "300",
"marginLeft": 10,
"marginVertical": 30,
},
Object {
"color": "#0d0e12",
},
Object {
"marginBottom": 0,
"marginTop": 30,
},
]
}
>
Toggle e2e encryption
</Text>
<View
accessible={true}
focusable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
}
}
>
<View>
<View
style={
Array [
Object {
"flexDirection": "column",
"paddingHorizontal": 14,
"paddingVertical": 4,
"width": "100%",
},
undefined,
]
}
>
<View
style={
Object {
"flexDirection": "row",
}
}
>
<View
style={
Array [
Object {
"borderRadius": 2,
"height": 20,
"width": 20,
},
Object {
"marginLeft": 16,
},
]
}
>
<View
accessible={true}
focusable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
}
}
>
<View
style={
Array [
Object {
"overflow": "hidden",
},
Object {
"borderRadius": 2,
"height": 20,
"width": 20,
},
]
}
>
<FastImageView
resizeMode="cover"
source={
Object {
"headers": undefined,
"priority": "high",
"uri": "https://open.rocket.chat/avatar/diego.mello?format=png&size=20",
}
}
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
</View>
</View>
</View>
<View
style={
Array [
Object {
"flex": 1,
"marginLeft": 46,
},
Object {
"marginLeft": 10,
},
]
}
>
<Text
accessibilityLabel="This room's encryption has been disabled by diego.mello"
style={
Array [
Object {
"backgroundColor": "transparent",
"fontFamily": "System",
"fontSize": 16,
"fontStyle": "italic",
"fontWeight": "400",
"textAlign": "left",
},
Object {
"color": "#9ca2a8",
},
]
}
>
This room's encryption has been disabled by diego.mello
</Text>
</View>
</View>
</View>
</View>
</View>
<View
accessible={true}
focusable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
}
}
>
<View>
<View
style={
Array [
Object {
"flexDirection": "column",
"paddingHorizontal": 14,
"paddingVertical": 4,
"width": "100%",
},
undefined,
]
}
>
<View
style={
Object {
"flexDirection": "row",
}
}
>
<View
style={
Array [
Object {
"borderRadius": 2,
"height": 20,
"width": 20,
},
Object {
"marginLeft": 16,
},
]
}
>
<View
accessible={true}
focusable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
}
}
>
<View
style={
Array [
Object {
"overflow": "hidden",
},
Object {
"borderRadius": 2,
"height": 20,
"width": 20,
},
]
}
>
<FastImageView
resizeMode="cover"
source={
Object {
"headers": undefined,
"priority": "high",
"uri": "https://open.rocket.chat/avatar/diego.mello?format=png&size=20",
}
}
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
</View>
</View>
</View>
<View
style={
Array [
Object {
"flex": 1,
"marginLeft": 46,
},
Object {
"marginLeft": 10,
},
]
}
>
<Text
accessibilityLabel="This room's encryption has been enabled by diego.mello"
style={
Array [
Object {
"backgroundColor": "transparent",
"fontFamily": "System",
"fontSize": 16,
"fontStyle": "italic",
"fontWeight": "400",
"textAlign": "left",
},
Object {
"color": "#9ca2a8",
},
]
}
>
This room's encryption has been enabled by diego.mello
</Text>
</View>
</View>
</View>
</View>
</View>
<Text
style={
Array [
......@@ -144,7 +144,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode VERSIONCODE as Integer
versionName "4.14.1"
versionName "4.15.0"
vectorDrawables.useSupportLibrary = true
if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
......
......@@ -29,7 +29,7 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTop"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
......
......@@ -70,3 +70,5 @@ export const SETTINGS = createRequestTypes('SETTINGS', ['CLEAR', 'ADD']);
export const APP_STATE = createRequestTypes('APP_STATE', ['FOREGROUND', 'BACKGROUND']);
export const ENTERPRISE_MODULES = createRequestTypes('ENTERPRISE_MODULES', ['CLEAR', 'SET']);
export const ENCRYPTION = createRequestTypes('ENCRYPTION', ['INIT', 'STOP', 'DECODE_KEY', 'SET', 'SET_BANNER']);
export const PERMISSIONS = createRequestTypes('PERMISSIONS', ['SET']);
import * as types from './actionsTypes';
export function setPermissions(permissions) {
return {
type: types.PERMISSIONS.SET,
permissions
};
}
......@@ -63,6 +63,7 @@ export const themes = {
passcodeDotFull: '#6C727A',
previewBackground: '#1F2329',
previewTintColor: '#ffffff',
backdropOpacity: 0.3,
...mentions
},
dark: {
......@@ -109,6 +110,7 @@ export const themes = {
passcodeDotFull: '#6C727A',
previewBackground: '#030b1b',
previewTintColor: '#ffffff',
backdropOpacity: 0.9,
...mentions
},
black: {
......@@ -155,6 +157,7 @@ export const themes = {
passcodeDotFull: '#6C727A',
previewBackground: '#000000',
previewTintColor: '#ffffff',
backdropOpacity: 0.9,
...mentions
}
};
......@@ -101,6 +101,9 @@ export default {
Jitsi_Enabled_TokenAuth: {
type: 'valueAsBoolean'
},
Jitsi_URL_Room_Hash: {
type: 'valueAsBoolean'
},
Jitsi_URL_Room_Prefix: {
type: 'valueAsString'
},
......
......@@ -147,7 +147,7 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }, ref) => {
const animatedPosition = React.useRef(new Value(0));
const opacity = interpolate(animatedPosition.current, {
inputRange: [0, 1],
outputRange: [0, 0.7],
outputRange: [0, themes[theme].backdropOpacity],
extrapolate: Extrapolate.CLAMP
});
......
......@@ -2,7 +2,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Q } from '@nozbe/watermelondb';
import isEqual from 'react-fast-compare';
import database from '../../lib/database';
import { getUserSelector } from '../../selectors/login';
......@@ -34,7 +33,8 @@ class AvatarContainer extends React.Component {
}
componentDidUpdate(prevProps) {
if (!isEqual(prevProps, this.props)) {
const { text, type } = this.props;
if (prevProps.text !== text || prevProps.type !== type) {
this.init();
}
}
......@@ -52,8 +52,8 @@ class AvatarContainer extends React.Component {
init = async() => {
const db = database.active;
const usersCollection = db.collections.get('users');
const subsCollection = db.collections.get('subscriptions');
const usersCollection = db.get('users');
const subsCollection = db.get('subscriptions');
let record;
try {
......
......@@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { View } from 'react-native';
import PropTypes from 'prop-types';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import equal from 'deep-equal';
import { dequal } from 'dequal';
import { connect } from 'react-redux';
import orderBy from 'lodash/orderBy';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
......@@ -67,7 +67,7 @@ class EmojiPicker extends Component {
if (nextState.width !== width) {
return true;
}
if (!equal(nextState.frequentlyUsed, frequentlyUsed)) {
if (!dequal(nextState.frequentlyUsed, frequentlyUsed)) {
return true;
}
return false;
......@@ -95,7 +95,7 @@ class EmojiPicker extends Component {
// eslint-disable-next-line react/sort-comp
_addFrequentlyUsed = protectedFunction(async(emoji) => {
const db = database.active;
const freqEmojiCollection = db.collections.get('frequently_used_emojis');
const freqEmojiCollection = db.get('frequently_used_emojis');
let freqEmojiRecord;
try {
freqEmojiRecord = await freqEmojiCollection.find(emoji.content);
......@@ -120,7 +120,7 @@ class EmojiPicker extends Component {
updateFrequentlyUsed = async() => {
const db = database.active;
const frequentlyUsedRecords = await db.collections.get('frequently_used_emojis').query().fetch();
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
let frequentlyUsed = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
frequentlyUsed = frequentlyUsed.map((item) => {
if (item.isCustom) {
......
import React, { memo, useEffect } from 'react';
import PropTypes from 'prop-types';
import { NotifierRoot, Notifier, Easing } from 'react-native-notifier';
import { connect } from 'react-redux';
import { dequal } from 'dequal';
import NotifierComponent from './NotifierComponent';
import EventEmitter from '../../utils/events';
......@@ -8,13 +11,17 @@ import { getActiveRoute } from '../../utils/navigation';
export const INAPP_NOTIFICATION_EMITTER = 'NotificationInApp';
const InAppNotification = memo(() => {
const InAppNotification = memo(({ rooms, appState }) => {
const show = (notification) => {
if (appState !== 'foreground') {
return;
}
const { payload } = notification;
const state = Navigation.navigationRef.current?.getRootState();
const route = getActiveRoute(state);
if (payload.rid) {
if ((route?.name === 'RoomView' && route.params?.rid === payload.rid) || route?.name === 'JitsiMeetView') {
if (rooms.includes(payload.rid) || route?.name === 'JitsiMeetView') {
return;
}
Notifier.showNotification({
......@@ -28,13 +35,23 @@ const InAppNotification = memo(() => {
};
useEffect(() => {
EventEmitter.addEventListener(INAPP_NOTIFICATION_EMITTER, show);
const listener = EventEmitter.addEventListener(INAPP_NOTIFICATION_EMITTER, show);
return () => {
EventEmitter.removeListener(INAPP_NOTIFICATION_EMITTER);
EventEmitter.removeListener(INAPP_NOTIFICATION_EMITTER, listener);
};
}, []);
}, [rooms]);
return <NotifierRoot />;
}, (prevProps, nextProps) => dequal(prevProps.rooms, nextProps.rooms));
const mapStateToProps = state => ({
rooms: state.room.rooms,
appState: state.app.ready && state.app.foreground ? 'foreground' : 'background'
});
export default InAppNotification;
InAppNotification.propTypes = {
rooms: PropTypes.array,
appState: PropTypes.string
};
export default connect(mapStateToProps)(InAppNotification);
......@@ -96,7 +96,7 @@ const Header = React.memo(({
const setEmojis = async() => {
try {
const db = database.active;
const freqEmojiCollection = db.collections.get('frequently_used_emojis');
const freqEmojiCollection = db.get('frequently_used_emojis');
let freqEmojis = await freqEmojiCollection.query().fetch();
const isLandscape = width > height;
......
......@@ -34,20 +34,24 @@ const MessageActions = React.memo(forwardRef(({
Message_AllowPinning,
Message_AllowStarring,
Message_Read_Receipt_Store_Users,
isMasterDetail
isMasterDetail,
editMessagePermission,
deleteMessagePermission,
forceDeleteMessagePermission,
pinMessagePermission
}, ref) => {
let permissions = {};
const { showActionSheet, hideActionSheet } = useActionSheet();
const getPermissions = async() => {
try {
const permission = ['edit-message', 'delete-message', 'force-delete-message'</