Merge branch 'chore.upgrade-ts-deps' into chore.upgrade-rn-0.73.6

# Conflicts:
#	ios/Podfile.lock
#	package.json
#	yarn.lock
This commit is contained in:
Diego Mello 2024-03-27 18:33:44 -03:00
commit be2a46b641
25 changed files with 4050 additions and 3362 deletions

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ const Render = () => (
);
const TODAY = '2023-04-01T00:00:00.000Z';
jest.useFakeTimers('modern');
jest.useFakeTimers();
jest.setSystemTime(new Date(TODAY));
describe('SupportedVersionsWarning', () => {

View File

@ -158,13 +158,8 @@ export const Code = () => (
<Markdown
msg='Inline `code` has `back-ticks around` it.
```
Code block 1
```
And other code block in sequence
```
Code block 2
```
'
Code block
```'
theme={theme}
/>
</View>

View File

@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
import { Image, StyleProp, Text, TextStyle, View } from 'react-native';
import { Image, StyleProp, Text, TextStyle } from 'react-native';
import { Parser } from 'commonmark';
import Renderer from 'commonmark-react-renderer';
import { MarkdownAST } from '@rocket.chat/message-parser';
@ -171,18 +171,19 @@ class Markdown extends PureComponent<IMarkdownProps, any> {
renderCodeBlock = ({ literal }: TLiteral) => {
const { theme, style = [] } = this.props;
return (
<View
<Text
style={[
{
...styles.codeBlock,
color: themes[theme!].bodyText,
backgroundColor: themes[theme!].bannerBackground,
borderColor: themes[theme!].borderColor
borderColor: themes[theme!].bannerBackground
},
...style
]}
>
<Text style={[styles.codeBlockText, { color: themes[theme!].bodyText }]}>{literal}</Text>
</View>
{literal}
</Text>
);
};

View File

@ -1,6 +1,4 @@
export default class Deferred {
[Symbol.toStringTag]: 'Promise';
private promise: Promise<unknown>;
private _resolve: (value?: unknown) => void;
private _reject: (reason?: any) => void;

View File

@ -34,7 +34,7 @@ export const useEndpointData = <TPath extends PathFor<'GET'>>(
if (!endpoint) return;
setLoading(true);
sdk
.get(endpoint, params)
.get(endpoint, params as any)
.then(e => {
setLoading(false);
if (e.success) {

View File

@ -124,7 +124,7 @@ jest.mock('../../../app-supportedversions.json', () => ({
]
}));
jest.useFakeTimers('modern');
jest.useFakeTimers();
jest.setSystemTime(new Date(TODAY));
describe('checkSupportedVersions', () => {

View File

@ -124,7 +124,7 @@ jest.mock('../../../app-supportedversions.json', () => ({
]
}));
jest.useFakeTimers('modern');
jest.useFakeTimers();
jest.setSystemTime(new Date(TODAY));
describe('checkSupportedVersions', () => {

View File

@ -40,6 +40,7 @@ class FileUpload {
data.forEach(item => {
if (item.uri) {
// @ts-ignore
upload.formData.append(item.name, {
// @ts-ignore
uri: item.uri,

View File

@ -1,10 +1,8 @@
import React from 'react';
import React, { useEffect, useRef } from 'react';
import { Animated, Easing, FlatList, TouchableWithoutFeedback } from 'react-native';
import { withSafeAreaInsets } from 'react-native-safe-area-context';
import styles from '../styles';
import { themes } from '../../../lib/constants';
import { TSupportedThemes, withTheme } from '../../../theme';
import { useTheme } from '../../../theme';
import * as List from '../../../containers/List';
import DropdownItemFilter from './DropdownItemFilter';
import DropdownItemHeader from './DropdownItemHeader';
@ -12,35 +10,31 @@ import { ROW_HEIGHT } from './DropdownItem';
import { ILivechatDepartment } from '../../../definitions/ILivechatDepartment';
const ANIMATION_DURATION = 200;
const HEIGHT_DESTINATION = 0;
const MAX_ROWS = 5;
interface IDropdownProps {
theme?: TSupportedThemes;
currentDepartment: ILivechatDepartment;
onClose: () => void;
onDepartmentSelected: (value: ILivechatDepartment) => void;
departments: ILivechatDepartment[];
}
class Dropdown extends React.Component<IDropdownProps> {
private animatedValue: Animated.Value;
const Dropdown = ({ currentDepartment, onClose, onDepartmentSelected, departments }: IDropdownProps) => {
const animatedValue = useRef(new Animated.Value(0)).current;
const { colors } = useTheme();
constructor(props: IDropdownProps) {
super(props);
this.animatedValue = new Animated.Value(0);
}
componentDidMount() {
Animated.timing(this.animatedValue, {
useEffect(() => {
Animated.timing(animatedValue, {
toValue: 1,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
}).start();
}
}, [animatedValue]);
close = () => {
const { onClose } = this.props;
Animated.timing(this.animatedValue, {
const close = () => {
Animated.timing(animatedValue, {
toValue: 0,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
@ -48,58 +42,54 @@ class Dropdown extends React.Component<IDropdownProps> {
}).start(() => onClose());
};
render() {
const { theme, currentDepartment, onDepartmentSelected, departments } = this.props;
const heightDestination = 0;
const translateY = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-300, heightDestination] // approximated height of the component when closed/open
});
const backdropOpacity = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, themes[theme!].backdropOpacity]
});
const translateY = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-300, HEIGHT_DESTINATION] // approximated height of the component when closed/open
});
const maxRows = 5;
return (
<>
<TouchableWithoutFeedback onPress={this.close}>
<Animated.View
style={[
styles.backdrop,
{
backgroundColor: themes[theme!].backdropColor,
opacity: backdropOpacity,
top: heightDestination
}
]}
/>
</TouchableWithoutFeedback>
const backdropOpacity = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, colors.backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={close}>
<Animated.View
style={[
styles.dropdownContainer,
styles.backdrop,
{
transform: [{ translateY }],
backgroundColor: themes[theme!].backgroundColor,
borderColor: themes[theme!].separatorColor
backgroundColor: colors.backdropColor,
opacity: backdropOpacity,
top: HEIGHT_DESTINATION
}
]}
>
<DropdownItemHeader department={currentDepartment} onPress={this.close} />
<List.Separator />
<FlatList
style={{ maxHeight: maxRows * ROW_HEIGHT }}
data={departments}
keyExtractor={item => item._id}
renderItem={({ item }) => (
<DropdownItemFilter onPress={onDepartmentSelected} currentDepartment={currentDepartment} value={item} />
)}
keyboardShouldPersistTaps='always'
/>
</Animated.View>
</>
);
}
}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
styles.dropdownContainer,
{
transform: [{ translateY }],
backgroundColor: colors.backgroundColor,
borderColor: colors.separatorColor
}
]}
>
<DropdownItemHeader department={currentDepartment} onPress={close} />
<List.Separator />
<FlatList
style={{ maxHeight: MAX_ROWS * ROW_HEIGHT }}
data={departments}
keyExtractor={item => item._id}
renderItem={({ item }) => (
<DropdownItemFilter onPress={onDepartmentSelected} currentDepartment={currentDepartment} value={item} />
)}
keyboardShouldPersistTaps='always'
/>
</Animated.View>
</>
);
};
export default withTheme(withSafeAreaInsets(Dropdown));
export default Dropdown;

View File

@ -138,11 +138,13 @@ const ChangeAvatarView = () => {
cropperAvoidEmptySpaceAroundImage: false,
cropperChooseText: I18n.t('Choose'),
cropperCancelText: I18n.t('Cancel'),
includeBase64: true,
useFrontCamera: isCam
includeBase64: true
};
try {
const response: Image = isCam === true ? await ImagePicker.openCamera(options) : await ImagePicker.openPicker(options);
const response: Image =
isCam === true
? await ImagePicker.openCamera({ ...options, useFrontCamera: true })
: await ImagePicker.openPicker(options);
dispatchAvatar({
type: AvatarStateActions.CHANGE_AVATAR,
payload: { url: response.path, data: `data:image/jpeg;base64,${response.data}`, service: 'upload' }

View File

@ -1,13 +1,13 @@
import React, { PureComponent } from 'react';
import React, { useEffect, useRef } from 'react';
import { Animated, Easing, Switch, Text, TouchableWithoutFeedback, View } from 'react-native';
import Touch from '../../containers/Touch';
import { CustomIcon, TIconsName } from '../../containers/CustomIcon';
import Check from '../../containers/Check';
import I18n from '../../i18n';
import { SWITCH_TRACK_COLOR, themes } from '../../lib/constants';
import { SWITCH_TRACK_COLOR } from '../../lib/constants';
import styles from './styles';
import { TSupportedThemes } from '../../theme';
import { useTheme } from '../../theme';
const ANIMATION_DURATION = 200;
const ANIMATION_PROPS = {
@ -23,34 +23,34 @@ interface IDirectoryOptionsProps {
close: Function;
changeType: Function;
toggleWorkspace(): void;
theme: TSupportedThemes;
}
export default class DirectoryOptions extends PureComponent<IDirectoryOptionsProps, any> {
private animatedValue: Animated.Value;
const DirectoryOptions = ({
type: propType,
globalUsers,
isFederationEnabled,
close: onClose,
changeType,
toggleWorkspace
}: IDirectoryOptionsProps) => {
const animatedValue = useRef(new Animated.Value(0)).current;
const { colors } = useTheme();
constructor(props: IDirectoryOptionsProps) {
super(props);
this.animatedValue = new Animated.Value(0);
}
componentDidMount() {
Animated.timing(this.animatedValue, {
useEffect(() => {
Animated.timing(animatedValue, {
toValue: 1,
...ANIMATION_PROPS
}).start();
}
}, [animatedValue]);
close = () => {
const { close } = this.props;
Animated.timing(this.animatedValue, {
const close = () => {
Animated.timing(animatedValue, {
toValue: 0,
...ANIMATION_PROPS
}).start(() => close());
}).start(() => onClose());
};
renderItem = (itemType: string) => {
const { changeType, type: propType, theme } = this.props;
const renderItem = (itemType: string) => {
let text = 'Users';
let icon: TIconsName = 'user';
if (itemType === 'channels') {
@ -66,70 +66,61 @@ export default class DirectoryOptions extends PureComponent<IDirectoryOptionsPro
return (
<Touch onPress={() => changeType(itemType)} style={styles.dropdownItemButton} accessibilityLabel={I18n.t(text)}>
<View style={styles.dropdownItemContainer}>
<CustomIcon name={icon} size={22} color={themes[theme].bodyText} style={styles.dropdownItemIcon} />
<Text style={[styles.dropdownItemText, { color: themes[theme].bodyText }]}>{I18n.t(text)}</Text>
<CustomIcon name={icon} size={22} color={colors.bodyText} style={styles.dropdownItemIcon} />
<Text style={[styles.dropdownItemText, { color: colors.bodyText }]}>{I18n.t(text)}</Text>
{propType === itemType ? <Check /> : null}
</View>
</Touch>
);
};
render() {
const translateY = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-326, 0]
});
const { globalUsers, toggleWorkspace, isFederationEnabled, theme } = this.props;
const backdropOpacity = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, themes[theme].backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={this.close}>
<Animated.View style={[styles.backdrop, { backgroundColor: themes[theme].backdropColor, opacity: backdropOpacity }]} />
</TouchableWithoutFeedback>
<Animated.View
style={[styles.dropdownContainer, { transform: [{ translateY }], backgroundColor: themes[theme].backgroundColor }]}
>
<Touch onPress={this.close} accessibilityLabel={I18n.t('Search_by')}>
<View
style={[
styles.dropdownContainerHeader,
styles.dropdownItemContainer,
{ borderColor: themes[theme].separatorColor }
]}
>
<Text style={[styles.dropdownToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Search_by')}</Text>
<CustomIcon
style={[styles.dropdownItemIcon, styles.inverted]}
size={22}
name='chevron-down'
color={themes[theme].auxiliaryTintColor}
/>
</View>
</Touch>
{this.renderItem('channels')}
{this.renderItem('users')}
{this.renderItem('teams')}
{isFederationEnabled ? (
<>
<View style={[styles.dropdownSeparator, { backgroundColor: themes[theme].separatorColor }]} />
<View style={[styles.dropdownItemContainer, styles.globalUsersContainer]}>
<View style={styles.globalUsersTextContainer}>
<Text style={[styles.dropdownItemText, { color: themes[theme].infoText }]}>
{I18n.t('Search_global_users')}
</Text>
<Text style={[styles.dropdownItemDescription, { color: themes[theme].infoText }]}>
{I18n.t('Search_global_users_description')}
</Text>
</View>
<Switch value={globalUsers} onValueChange={toggleWorkspace} trackColor={SWITCH_TRACK_COLOR} />
const translateY = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-326, 0]
});
const backdropOpacity = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, colors.backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={close}>
<Animated.View style={[styles.backdrop, { backgroundColor: colors.backdropColor, opacity: backdropOpacity }]} />
</TouchableWithoutFeedback>
<Animated.View style={[styles.dropdownContainer, { transform: [{ translateY }], backgroundColor: colors.backgroundColor }]}>
<Touch onPress={close} accessibilityLabel={I18n.t('Search_by')}>
<View style={[styles.dropdownContainerHeader, styles.dropdownItemContainer, { borderColor: colors.separatorColor }]}>
<Text style={[styles.dropdownToggleText, { color: colors.auxiliaryText }]}>{I18n.t('Search_by')}</Text>
<CustomIcon
style={[styles.dropdownItemIcon, styles.inverted]}
size={22}
name='chevron-down'
color={colors.auxiliaryTintColor}
/>
</View>
</Touch>
{renderItem('channels')}
{renderItem('users')}
{renderItem('teams')}
{isFederationEnabled ? (
<>
<View style={[styles.dropdownSeparator, { backgroundColor: colors.separatorColor }]} />
<View style={[styles.dropdownItemContainer, styles.globalUsersContainer]}>
<View style={styles.globalUsersTextContainer}>
<Text style={[styles.dropdownItemText, { color: colors.infoText }]}>{I18n.t('Search_global_users')}</Text>
<Text style={[styles.dropdownItemDescription, { color: colors.infoText }]}>
{I18n.t('Search_global_users_description')}
</Text>
</View>
</>
) : null}
</Animated.View>
</>
);
}
}
<Switch value={globalUsers} onValueChange={toggleWorkspace} trackColor={SWITCH_TRACK_COLOR} />
</View>
</>
) : null}
</Animated.View>
</>
);
};
export default DirectoryOptions;

View File

@ -315,7 +315,6 @@ class DirectoryView extends React.Component<IDirectoryViewProps, IDirectoryViewS
/>
{showOptionsDropdown ? (
<Options
theme={theme}
type={type}
globalUsers={globalUsers}
close={this.toggleDropdown}

View File

@ -524,7 +524,6 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
const { room, member, joined, canForwardGuest, canReturnQueue, canViewCannedResponse, canPlaceLivechatOnHold } = this.state;
const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
// @ts-ignore
navigation.navigate('ModalStackNavigator', {
screen: screen ?? 'RoomActionsView',
params: {
@ -533,6 +532,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
room: room as ISubscription,
member,
showCloseModal: !!screen,
// @ts-ignore
joined,
omnichannelPermissions: { canForwardGuest, canReturnQueue, canViewCannedResponse, canPlaceLivechatOnHold }
}

View File

@ -1,8 +1,8 @@
import React, { Component } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Linking } from 'react-native';
import { batch, connect } from 'react-redux';
import { withSafeAreaInsets } from 'react-native-safe-area-context';
import { batch, useDispatch } from 'react-redux';
import { Subscription } from 'rxjs';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import * as List from '../../containers/List';
import Button from '../../containers/Button';
@ -13,82 +13,73 @@ import I18n from '../../i18n';
import EventEmitter from '../../lib/methods/helpers/events';
import ServerItem from '../../containers/ServerItem';
import database from '../../lib/database';
import { themes, TOKEN_KEY } from '../../lib/constants';
import { withTheme } from '../../theme';
import { TOKEN_KEY } from '../../lib/constants';
import { useTheme } from '../../theme';
import { localAuthenticate } from '../../lib/methods/helpers/localAuthentication';
import { showConfirmationAlert } from '../../lib/methods/helpers/info';
import log, { events, logEvent } from '../../lib/methods/helpers/log';
import { headerHeight } from '../../lib/methods/helpers/navigation';
import { goRoom } from '../../lib/methods/helpers/goRoom';
import UserPreferences from '../../lib/methods/userPreferences';
import { IApplicationState, IBaseScreen, RootEnum, TServerModel } from '../../definitions';
import { RootEnum, TServerModel } from '../../definitions';
import styles from './styles';
import { ChatsStackParamList } from '../../stacks/types';
import { removeServer } from '../../lib/methods';
import { useAppSelector } from '../../lib/hooks';
const ROW_HEIGHT = 68;
const ANIMATION_DURATION = 200;
const MAX_ROWS = 4;
interface IServerDropdownProps extends IBaseScreen<ChatsStackParamList, 'RoomsListView'> {
insets?: {
top: number;
};
closeServerDropdown: boolean;
server: string;
isMasterDetail: boolean;
}
const ServerDropdown = () => {
const animatedValue = useRef(new Animated.Value(0)).current;
const subscription = useRef<Subscription>();
const newServerTimeout = useRef<ReturnType<typeof setTimeout> | false>();
const isMounted = useRef(false);
const [servers, setServers] = useState<TServerModel[]>([]);
const dispatch = useDispatch();
const closeServerDropdown = useAppSelector(state => state.rooms.closeServerDropdown);
const server = useAppSelector(state => state.server.server);
const isMasterDetail = useAppSelector(state => state.app.isMasterDetail);
const { colors } = useTheme();
const insets = useSafeAreaInsets();
interface IServerDropdownState {
servers: TServerModel[];
}
useEffect(() => {
if (isMounted.current) close();
}, [closeServerDropdown]);
class ServerDropdown extends Component<IServerDropdownProps, IServerDropdownState> {
private animatedValue: Animated.Value;
private subscription?: Subscription;
private newServerTimeout?: ReturnType<typeof setTimeout> | false;
useEffect(() => {
isMounted.current = true;
constructor(props: IServerDropdownProps) {
super(props);
this.state = { servers: [] };
this.animatedValue = new Animated.Value(0);
}
const init = async () => {
const serversDB = database.servers;
const observable = await serversDB.get('servers').query().observeWithColumns(['name']);
async componentDidMount() {
const serversDB = database.servers;
const observable = await serversDB.get('servers').query().observeWithColumns(['name']);
subscription.current = observable.subscribe(data => {
setServers(data);
});
this.subscription = observable.subscribe(data => {
this.setState({ servers: data });
});
Animated.timing(animatedValue, {
toValue: 1,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
}).start();
};
init();
Animated.timing(this.animatedValue, {
toValue: 1,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
}).start();
}
return () => {
if (newServerTimeout.current) {
clearTimeout(newServerTimeout.current);
newServerTimeout.current = false;
}
if (subscription.current && subscription.current.unsubscribe) {
subscription.current.unsubscribe();
}
};
}, []);
componentDidUpdate(prevProps: IServerDropdownProps) {
const { closeServerDropdown } = this.props;
if (prevProps.closeServerDropdown !== closeServerDropdown) {
this.close();
}
}
componentWillUnmount() {
if (this.newServerTimeout) {
clearTimeout(this.newServerTimeout);
this.newServerTimeout = false;
}
if (this.subscription && this.subscription.unsubscribe) {
this.subscription.unsubscribe();
}
}
close = () => {
const { dispatch } = this.props;
Animated.timing(this.animatedValue, {
const close = () => {
Animated.timing(animatedValue, {
toValue: 0,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
@ -96,7 +87,7 @@ class ServerDropdown extends Component<IServerDropdownProps, IServerDropdownStat
}).start(() => dispatch(toggleServerDropdown()));
};
createWorkspace = async () => {
const createWorkspace = async () => {
logEvent(events.RL_CREATE_NEW_WORKSPACE);
try {
await Linking.openURL('https://cloud.rocket.chat/trial');
@ -105,52 +96,49 @@ class ServerDropdown extends Component<IServerDropdownProps, IServerDropdownStat
}
};
navToNewServer = (previousServer: string) => {
const { dispatch } = this.props;
const navToNewServer = (previousServer: string) => {
batch(() => {
dispatch(appStart({ root: RootEnum.ROOT_OUTSIDE }));
dispatch(serverInitAdd(previousServer));
});
};
addServer = () => {
const addServer = () => {
logEvent(events.RL_ADD_SERVER);
const { server } = this.props;
this.close();
close();
setTimeout(() => {
this.navToNewServer(server);
navToNewServer(server);
}, ANIMATION_DURATION);
};
select = async (server: string, version?: string) => {
const { server: currentServer, dispatch, isMasterDetail } = this.props;
this.close();
if (currentServer !== server) {
const select = async (serverParam: string, version?: string) => {
close();
if (server !== serverParam) {
logEvent(events.RL_CHANGE_SERVER);
const userId = UserPreferences.getString(`${TOKEN_KEY}-${server}`);
const userId = UserPreferences.getString(`${TOKEN_KEY}-${serverParam}`);
if (isMasterDetail) {
goRoom({ item: {}, isMasterDetail });
}
if (!userId) {
setTimeout(() => {
this.navToNewServer(currentServer);
this.newServerTimeout = setTimeout(() => {
EventEmitter.emit('NewServer', { server });
navToNewServer(server);
newServerTimeout.current = setTimeout(() => {
EventEmitter.emit('NewServer', { server: serverParam });
}, ANIMATION_DURATION);
}, ANIMATION_DURATION);
} else {
await localAuthenticate(server);
dispatch(selectServerRequest(server, version, true, true));
await localAuthenticate(serverParam);
dispatch(selectServerRequest(serverParam, version, true, true));
}
}
};
remove = (server: string) =>
const remove = (server: string) =>
showConfirmationAlert({
message: I18n.t('This_will_remove_all_data_from_this_server'),
confirmationText: I18n.t('Delete'),
onPress: async () => {
this.close();
close();
try {
await removeServer({ server });
} catch {
@ -159,93 +147,81 @@ class ServerDropdown extends Component<IServerDropdownProps, IServerDropdownStat
}
});
renderServer = ({ item }: { item: { id: string; iconURL: string; name: string; version: string } }) => {
const { server } = this.props;
const renderItem = ({ item }: { item: { id: string; iconURL: string; name: string; version: string } }) => (
<ServerItem
item={item}
onPress={() => select(item.id, item.version)}
onLongPress={() => item.id === server || remove(item.id)}
hasCheck={item.id === server}
/>
);
return (
<ServerItem
item={item}
onPress={() => this.select(item.id, item.version)}
onLongPress={() => item.id === server || this.remove(item.id)}
hasCheck={item.id === server}
/>
);
};
const initialTop = 87 + Math.min(servers.length, MAX_ROWS) * ROW_HEIGHT;
const statusBarHeight = insets?.top ?? 0;
const heightDestination = isMasterDetail ? headerHeight + statusBarHeight : 0;
render() {
const { servers } = this.state;
const { theme, isMasterDetail, insets } = this.props;
const maxRows = 4;
const initialTop = 87 + Math.min(servers.length, maxRows) * ROW_HEIGHT;
const statusBarHeight = insets?.top ?? 0;
const heightDestination = isMasterDetail ? headerHeight + statusBarHeight : 0;
const translateY = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-initialTop, heightDestination]
});
const backdropOpacity = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, themes[theme].backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={this.close}>
<Animated.View
style={[
styles.backdrop,
{
backgroundColor: themes[theme].backdropColor,
opacity: backdropOpacity,
top: heightDestination
}
]}
/>
</TouchableWithoutFeedback>
const translateY = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-initialTop, heightDestination]
});
const backdropOpacity = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, colors.backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={close}>
<Animated.View
style={[
styles.dropdownContainer,
styles.backdrop,
{
transform: [{ translateY }],
backgroundColor: themes[theme].backgroundColor,
borderColor: themes[theme].separatorColor
backgroundColor: colors.backdropColor,
opacity: backdropOpacity,
top: heightDestination
}
]}
testID='rooms-list-header-server-dropdown'
>
<View style={[styles.dropdownContainerHeader, styles.serverHeader, { borderColor: themes[theme].separatorColor }]}>
<Text style={[styles.serverHeaderText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Server')}</Text>
<TouchableOpacity onPress={this.addServer} testID='rooms-list-header-server-add'>
<Text style={[styles.serverHeaderAdd, { color: themes[theme].tintColor }]}>{I18n.t('Add_Server')}</Text>
</TouchableOpacity>
</View>
<FlatList
style={{ maxHeight: maxRows * ROW_HEIGHT }}
data={servers}
keyExtractor={item => item.id}
renderItem={this.renderServer}
ItemSeparatorComponent={List.Separator}
keyboardShouldPersistTaps='always'
/>
<List.Separator />
<Button
title={I18n.t('Create_a_new_workspace')}
type='secondary'
onPress={this.createWorkspace}
testID='rooms-list-header-create-workspace-button'
style={styles.buttonCreateWorkspace}
color={themes[theme].tintColor}
styleText={[styles.serverHeaderAdd, { textAlign: 'center' }]}
/>
</Animated.View>
</>
);
}
}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
styles.dropdownContainer,
{
transform: [{ translateY }],
backgroundColor: colors.backgroundColor,
borderColor: colors.separatorColor
}
]}
testID='rooms-list-header-server-dropdown'
>
<View style={[styles.dropdownContainerHeader, styles.serverHeader, { borderColor: colors.separatorColor }]}>
<Text style={[styles.serverHeaderText, { color: colors.auxiliaryText }]}>{I18n.t('Server')}</Text>
<TouchableOpacity onPress={addServer} testID='rooms-list-header-server-add'>
<Text style={[styles.serverHeaderAdd, { color: colors.tintColor }]}>{I18n.t('Add_Server')}</Text>
</TouchableOpacity>
</View>
<FlatList
style={{ maxHeight: MAX_ROWS * ROW_HEIGHT }}
data={servers}
keyExtractor={item => item.id}
renderItem={renderItem}
ItemSeparatorComponent={List.Separator}
keyboardShouldPersistTaps='always'
/>
<List.Separator />
<Button
title={I18n.t('Create_a_new_workspace')}
type='secondary'
onPress={createWorkspace}
testID='rooms-list-header-create-workspace-button'
style={styles.buttonCreateWorkspace}
color={colors.tintColor}
styleText={[styles.serverHeaderAdd, { textAlign: 'center' }]}
/>
</Animated.View>
</>
);
};
const mapStateToProps = (state: IApplicationState) => ({
closeServerDropdown: state.rooms.closeServerDropdown,
server: state.server.server,
isMasterDetail: state.app.isMasterDetail
});
export default connect(mapStateToProps)(withSafeAreaInsets(withTheme(ServerDropdown)));
export default ServerDropdown;

View File

@ -986,16 +986,14 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
render = () => {
console.count(`${this.constructor.name}.render calls`);
const { showServerDropdown, theme, navigation } = this.props;
const { showServerDropdown, theme } = this.props;
return (
<SafeAreaView testID='rooms-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
<StatusBar />
{this.renderHeader()}
{this.renderScroll()}
{/* TODO - this ts-ignore is here because the route props, on IBaseScreen*/}
{/* @ts-ignore*/}
{showServerDropdown ? <ServerDropdown navigation={navigation} theme={theme} /> : null}
{showServerDropdown ? <ServerDropdown /> : null}
</SafeAreaView>
);
};

View File

@ -1,47 +1,40 @@
import React from 'react';
import React, { useEffect, useRef } from 'react';
import { Animated, Easing, TouchableWithoutFeedback } from 'react-native';
import { EdgeInsets, withSafeAreaInsets } from 'react-native-safe-area-context';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import styles from '../styles';
import { themes } from '../../../lib/constants';
import { TSupportedThemes, withTheme } from '../../../theme';
import { headerHeight } from '../../../lib/methods/helpers/navigation';
import * as List from '../../../containers/List';
import { Filter } from '../filters';
import DropdownItemFilter from './DropdownItemFilter';
import DropdownItemHeader from './DropdownItemHeader';
import { useTheme } from '../../../theme';
const ANIMATION_DURATION = 200;
interface IDropdownProps {
isMasterDetail?: boolean;
theme: TSupportedThemes;
insets?: EdgeInsets;
currentFilter: Filter;
onClose: () => void;
onFilterSelected: (value: Filter) => void;
}
class Dropdown extends React.Component<IDropdownProps> {
private animatedValue: Animated.Value;
const Dropdown = ({ isMasterDetail, currentFilter, onClose, onFilterSelected }: IDropdownProps) => {
const animatedValue = useRef(new Animated.Value(0)).current;
const { colors } = useTheme();
const insets = useSafeAreaInsets();
constructor(props: IDropdownProps) {
super(props);
this.animatedValue = new Animated.Value(0);
}
componentDidMount() {
Animated.timing(this.animatedValue, {
useEffect(() => {
Animated.timing(animatedValue, {
toValue: 1,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
}).start();
}
}, [animatedValue]);
close = () => {
const { onClose } = this.props;
Animated.timing(this.animatedValue, {
const close = () => {
Animated.timing(animatedValue, {
toValue: 0,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
@ -49,51 +42,50 @@ class Dropdown extends React.Component<IDropdownProps> {
}).start(() => onClose());
};
render() {
const { isMasterDetail, insets, theme, currentFilter, onFilterSelected } = this.props;
const statusBarHeight = insets?.top ?? 0;
const heightDestination = isMasterDetail ? headerHeight + statusBarHeight : 0;
const translateY = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-300, heightDestination] // approximated height of the component when closed/open
});
const backdropOpacity = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, themes[theme].backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={this.close}>
<Animated.View
style={[
styles.backdrop,
{
backgroundColor: themes[theme].backdropColor,
opacity: backdropOpacity,
top: heightDestination
}
]}
/>
</TouchableWithoutFeedback>
const heightDestination = isMasterDetail ? headerHeight + insets.top : 0;
const translateY = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-300, heightDestination] // approximated height of the component when closed/open
});
const backdropOpacity = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, colors.backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={close}>
<Animated.View
style={[
styles.dropdownContainer,
styles.backdrop,
{
transform: [{ translateY }],
backgroundColor: themes[theme].backgroundColor,
borderColor: themes[theme].separatorColor
backgroundColor: colors.backdropColor,
opacity: backdropOpacity,
top: heightDestination
}
]}
>
<DropdownItemHeader currentFilter={currentFilter} onPress={this.close} />
<List.Separator />
<DropdownItemFilter currentFilter={currentFilter} value={Filter.All} onPress={onFilterSelected} />
<DropdownItemFilter currentFilter={currentFilter} value={Filter.Following} onPress={onFilterSelected} />
<DropdownItemFilter currentFilter={currentFilter} value={Filter.Unread} onPress={onFilterSelected} />
</Animated.View>
</>
);
}
}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
styles.dropdownContainer,
{
transform: [{ translateY }],
backgroundColor: colors.backgroundColor,
borderColor: colors.separatorColor
}
]}
>
<DropdownItemHeader currentFilter={currentFilter} onPress={close} />
<List.Separator />
<DropdownItemFilter currentFilter={currentFilter} value={Filter.All} onPress={onFilterSelected} />
<DropdownItemFilter currentFilter={currentFilter} value={Filter.Following} onPress={onFilterSelected} />
<DropdownItemFilter currentFilter={currentFilter} value={Filter.Unread} onPress={onFilterSelected} />
</Animated.View>
</>
);
};
export default withTheme(withSafeAreaInsets(Dropdown));
export default Dropdown;

View File

@ -516,19 +516,13 @@ class ThreadMessagesView extends React.Component<IThreadMessagesViewProps, IThre
render() {
console.count(`${this.constructor.name}.render calls`);
const { showFilterDropdown, currentFilter } = this.state;
const { theme } = this.props;
return (
<SafeAreaView testID='thread-messages-view'>
<StatusBar />
{this.renderContent()}
{showFilterDropdown ? (
<Dropdown
currentFilter={currentFilter}
onFilterSelected={this.onFilterSelected}
onClose={this.closeFilterDropdown}
theme={theme}
/>
<Dropdown currentFilter={currentFilter} onFilterSelected={this.onFilterSelected} onClose={this.closeFilterDropdown} />
) : null}
</SafeAreaView>
);

View File

@ -1282,10 +1282,16 @@ PODS:
- TOCropViewController
- RNLocalize (2.1.1):
- React-Core
<<<<<<< HEAD
- RNNotifee (7.8.0):
=======
- RNMathView (1.0.0):
- iosMath
- RNNotifee (7.8.2):
>>>>>>> chore.upgrade-ts-deps
- React-Core
- RNNotifee/NotifeeCore (= 7.8.0)
- RNNotifee/NotifeeCore (7.8.0):
- RNNotifee/NotifeeCore (= 7.8.2)
- RNNotifee/NotifeeCore (7.8.2):
- React-Core
- RNReanimated (3.8.1):
- glog
@ -1773,8 +1779,14 @@ SPEC CHECKSUMS:
RNGestureHandler: 67fb54b3e6ca338a8044e85cd6f340265aa41091
RNImageCropPicker: 97289cd94fb01ab79db4e5c92938be4d0d63415d
RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b
<<<<<<< HEAD
RNNotifee: f3c01b391dd8e98e67f539f9a35a9cbcd3bae744
RNReanimated: 8a4d86eb951a4a99d8e86266dc71d7735c0c30a9
=======
RNMathView: 4c8a3c081fa671ab3136c51fa0bdca7ffb708bd5
RNNotifee: 8e2d3df3f0e9ce8f5d1fe4c967431138190b6175
RNReanimated: 64573e25e078ae6bec03b891586d50b9ec284393
>>>>>>> chore.upgrade-ts-deps
RNRootView: 895a4813dedeaca82db2fa868ca1c333d790e494
RNScreens: 17e2f657f1b09a71ec3c821368a04acbb7ebcb46
RNSVG: c1e76b81c76cdcd34b4e1188852892dc280eb902

View File

@ -28,11 +28,11 @@
"e2e:start": "RUNNING_E2E_TESTS=true npx react-native start"
},
"dependencies": {
"@bugsnag/react-native": "7.19.0",
"@codler/react-native-keyboard-aware-scroll-view": "2.0.1",
"@bugsnag/react-native": "^7.10.5",
"@codler/react-native-keyboard-aware-scroll-view": "^2.0.1",
"@gorhom/bottom-sheet": "4.4.5",
"@hookform/resolvers": "2.9.10",
"@notifee/react-native": "7.8.0",
"@hookform/resolvers": "^2.9.10",
"@notifee/react-native": "7.8.2",
"@nozbe/watermelondb": "0.25.5",
"@react-native-async-storage/async-storage": "^1.22.3",
"@react-native-camera-roll/camera-roll": "^7.5.0",
@ -57,7 +57,7 @@
"@rocket.chat/ui-kit": "0.31.19",
"bytebuffer": "5.0.1",
"color2k": "1.2.4",
"commonmark": "https://github.com/RocketChat/commonmark.js.git",
"commonmark": "git+https://github.com/RocketChat/commonmark.js.git",
"commonmark-react-renderer": "git+https://github.com/RocketChat/commonmark-react-renderer.git",
"dequal": "2.0.3",
"ejson": "2.2.3",
@ -156,31 +156,31 @@
"react-native-reanimated": "3.8.1"
},
"devDependencies": {
"@babel/core": "7.20.2",
"@babel/eslint-parser": "7.14.7",
"@babel/eslint-plugin": "7.13.0",
"@babel/plugin-proposal-decorators": "7.8.3",
"@babel/plugin-transform-named-capturing-groups-regex": "7.17.12",
"@babel/core": "^7.24.3",
"@babel/eslint-parser": "^7.24.1",
"@babel/eslint-plugin": "^7.23.5",
"@babel/plugin-proposal-decorators": "^7.24.1",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
"@babel/preset-env": "7.24.1",
"@babel/runtime": "7.24.1",
"@bugsnag/source-maps": "2.2.0",
"@babel/runtime": "^7.24.1",
"@bugsnag/source-maps": "^2.2.0",
"@react-native/babel-preset": "0.73.21",
"@react-native/eslint-config": "0.73.2",
"@react-native/metro-config": "0.73.5",
"@react-native/typescript-config": "0.73.1",
"@rocket.chat/eslint-config": "0.4.0",
"@rocket.chat/eslint-config": "^0.4.0",
"@storybook/addon-storyshots": "6.3",
"@storybook/react": "6.3",
"@storybook/react-native": "6.0.1-beta.7",
"@testing-library/react-hooks": "8.0.1",
"@testing-library/react-native": "12.4.3",
"@types/bytebuffer": "5.0.44",
"@types/ejson": "2.1.3",
"@types/i18n-js": "3.8.3",
"@types/jest": "26.0.24",
"@types/jsrsasign": "10.5.8",
"@types/lodash": "4.14.188",
"@types/react": "18.2.6",
"@storybook/react-native": "^6.0.1-beta.7",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/react-native": "^12.4.3",
"@types/bytebuffer": "^5.0.44",
"@types/ejson": "^2.1.3",
"@types/i18n-js": "^3.8.3",
"@types/jest": "^29.5.12",
"@types/jsrsasign": "^10.5.8",
"@types/lodash": "^4.14.188",
"@types/react": "^17.0.14",
"@types/react-native": "0.68.1",
"@types/react-native-background-timer": "2.0.0",
"@types/react-native-config-reader": "4.1.0",
@ -189,29 +189,29 @@
"@types/react-native-vector-icons": "6.4.12",
"@types/react-test-renderer": "18.0.0",
"@types/semver": "7.3.13",
"@types/ua-parser-js": "0.7.36",
"@types/url-parse": "1.4.8",
"@typescript-eslint/eslint-plugin": "4.28.3",
"@typescript-eslint/parser": "4.28.5",
"@types/ua-parser-js": "^0.7.36",
"@types/url-parse": "^1.4.8",
"@typescript-eslint/eslint-plugin": "^7.4.0",
"@typescript-eslint/parser": "^7.4.0",
"axios": "0.27.2",
"babel-jest": "29.6.3",
"babel-loader": "8.3.0",
"babel-plugin-transform-remove-console": "6.9.4",
"babel-jest": "^29.7.0",
"babel-loader": "^9.1.3",
"babel-plugin-transform-remove-console": "^6.9.4",
"codecov": "3.8.3",
"detox": "20.17.1",
"eslint": "8.19.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jest": "26.5.3",
"eslint-plugin-jsx-a11y": "6.5.1",
"eslint-plugin-react": "7.30.0",
"eslint-plugin-react-hooks": "4.5.0",
"eslint-plugin-react-native": "4.0.0",
"identity-obj-proxy": "3.0.0",
"jest": "29.6.3",
"jest-cli": "28.1.3",
"jest-expo": "^50.0.4",
"jest-junit": "15.0.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-native": "^4.1.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"jest-expo": "^46.0.1",
"jest-junit": "^16.0.0",
"otp.js": "1.2.0",
"patch-package": "8.0.0",
"prettier": "2.8.8",
@ -221,8 +221,8 @@
"react-test-renderer": "18.2.0",
"reactotron-redux": "3.1.3",
"reactotron-redux-saga": "4.2.3",
"ts-node": "10.9.1",
"typescript": "4.3.5"
"ts-node": "^10.9.1",
"typescript": "^5.4.3"
},
"jest-junit": {
"addFileAttribute": "true"

View File

@ -18,3 +18,24 @@
Notifee.REQUEST_CODE_NOTIFICATION_PERMISSION,
this);
}
diff --git a/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m b/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m
index cf8020d..3a1e080 100644
--- a/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m
+++ b/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m
@@ -179,11 +179,11 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
_notificationOpenedAppID = notifeeNotification[@"id"];
- // handle notification outside of notifee
- if (notifeeNotification == nil) {
- notifeeNotification =
- [NotifeeCoreUtil parseUNNotificationRequest:response.notification.request];
- }
+ // disable notifee handler on ios devices
+ // if (notifeeNotification == nil) {
+ // notifeeNotification =
+ // [NotifeeCoreUtil parseUNNotificationRequest:response.notification.request];
+ // }
if (notifeeNotification != nil) {
if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) {

View File

@ -1,8 +1,8 @@
diff --git a/node_modules/@types/ejson/index.d.ts b/node_modules/@types/ejson/index.d.ts
index 3a35636..278ef98 100755
index 7790dd7..f04dbc5 100644
--- a/node_modules/@types/ejson/index.d.ts
+++ b/node_modules/@types/ejson/index.d.ts
@@ -17,7 +17,7 @@ export function parse(str: string): any;
@@ -12,7 +12,7 @@ export function parse(str: string): any;
export function stringify(obj: any, options?: StringifyOptions): string;
export function toJSONValue(obj: any): string;

View File

@ -0,0 +1,13 @@
diff --git a/node_modules/commonmark/lib/inlines.js b/node_modules/commonmark/lib/inlines.js
index 4179cfd..478bbd5 100644
--- a/node_modules/commonmark/lib/inlines.js
+++ b/node_modules/commonmark/lib/inlines.js
@@ -996,7 +996,7 @@ var parseEmail = function(block) {
}
}
-var reHashtag = XRegExp.cache('^#(\\pL[\\pL\\d\\-_.]*[\\pL\\d])');
+var reHashtag = XRegExp.cache('^#([\\pL\\d\\-_.]*[\\pL\\d])');
var parseHashtag = function(block) {
if (this.brackets) {
// Don't perform autolinking while inside an explicit link

3921
yarn.lock

File diff suppressed because it is too large Load Diff