[NEW] Update room item animations (#4024)
* Upgrade react-native-gesture-handler to 2.3.0 * Update room item animations to reanimated v2 * Add Parallax animation on fav and hide buttons and additional swipe gesture to toggleFav * Fix tests * Ignore typescript error for setTimeout function * Update pods * Fix blank area on swiping all the way right/left * Fix Action Buttons on devices with notch * Update snapshot * Use colors from useTheme * Destructure props * Proper types for nativeEvent and event * Remove toggleFav gesture * Clean bits * Fix lint error * Fix position of Room Action Buttons on MasterDetail * Remove comment * Update animations logic * Add haptic feedback on swipe * Add haptic feedback on unswipe gesture * Update react-native-gesture-handler to 2.4.2 * update pods * Migrating off RNGHEnabledRootView * Update types to ReturnType<typeof setTimeout> Co-authored-by: GleidsonDaniel <gleidson10daniel@hotmail.com>
This commit is contained in:
parent
c76a1e6a4c
commit
02c1bc50b9
|
@ -12,7 +12,6 @@ import com.facebook.react.ReactRootView;
|
||||||
import com.facebook.react.ReactActivityDelegate;
|
import com.facebook.react.ReactActivityDelegate;
|
||||||
import com.facebook.react.ReactFragmentActivity;
|
import com.facebook.react.ReactFragmentActivity;
|
||||||
|
|
||||||
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
|
||||||
import com.zoontek.rnbootsplash.RNBootSplash;
|
import com.zoontek.rnbootsplash.RNBootSplash;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
@ -51,16 +50,6 @@ public class MainActivity extends ReactFragmentActivity {
|
||||||
return "RocketChatRN";
|
return "RocketChatRN";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
|
||||||
return new ReactActivityDelegate(this, getMainComponentName()) {
|
|
||||||
@Override
|
|
||||||
protected ReactRootView createRootView() {
|
|
||||||
return new RNGestureHandlerEnabledRootView(MainActivity.this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// from react-native-orientation
|
// from react-native-orientation
|
||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
|
|
@ -3,21 +3,10 @@ package chat.rocket.reactnative.share;
|
||||||
import com.facebook.react.ReactActivity;
|
import com.facebook.react.ReactActivity;
|
||||||
import com.facebook.react.ReactActivityDelegate;
|
import com.facebook.react.ReactActivityDelegate;
|
||||||
import com.facebook.react.ReactRootView;
|
import com.facebook.react.ReactRootView;
|
||||||
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
|
||||||
|
|
||||||
public class ShareActivity extends ReactActivity {
|
public class ShareActivity extends ReactActivity {
|
||||||
@Override
|
@Override
|
||||||
protected String getMainComponentName() {
|
protected String getMainComponentName() {
|
||||||
return "ShareRocketChatRN";
|
return "ShareRocketChatRN";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
|
||||||
return new ReactActivityDelegate(this, getMainComponentName()) {
|
|
||||||
@Override
|
|
||||||
protected ReactRootView createRootView() {
|
|
||||||
return new RNGestureHandlerEnabledRootView(ShareActivity.this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,25 +1,32 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Animated, View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
import Animated, {
|
||||||
|
useAnimatedStyle,
|
||||||
|
interpolate,
|
||||||
|
withSpring,
|
||||||
|
runOnJS,
|
||||||
|
useAnimatedReaction,
|
||||||
|
useSharedValue
|
||||||
|
} from 'react-native-reanimated';
|
||||||
import { RectButton } from 'react-native-gesture-handler';
|
import { RectButton } from 'react-native-gesture-handler';
|
||||||
|
import * as Haptics from 'expo-haptics';
|
||||||
|
|
||||||
import { isRTL } from '../../i18n';
|
|
||||||
import { CustomIcon } from '../CustomIcon';
|
import { CustomIcon } from '../CustomIcon';
|
||||||
import { DisplayMode, themes } from '../../lib/constants';
|
import { DisplayMode } from '../../lib/constants';
|
||||||
import styles, { ACTION_WIDTH, LONG_SWIPE, ROW_HEIGHT_CONDENSED } from './styles';
|
import styles, { ACTION_WIDTH, LONG_SWIPE, ROW_HEIGHT_CONDENSED } from './styles';
|
||||||
import { ILeftActionsProps, IRightActionsProps } from './interfaces';
|
import { ILeftActionsProps, IRightActionsProps } from './interfaces';
|
||||||
|
import { useTheme } from '../../theme';
|
||||||
|
import I18n from '../../i18n';
|
||||||
|
|
||||||
const reverse = new Animated.Value(isRTL() ? -1 : 1);
|
|
||||||
const CONDENSED_ICON_SIZE = 24;
|
const CONDENSED_ICON_SIZE = 24;
|
||||||
const EXPANDED_ICON_SIZE = 28;
|
const EXPANDED_ICON_SIZE = 28;
|
||||||
|
|
||||||
export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleReadPress, displayMode }: ILeftActionsProps) => {
|
export const LeftActions = React.memo(({ transX, isRead, width, onToggleReadPress, displayMode }: ILeftActionsProps) => {
|
||||||
const translateX = Animated.multiply(
|
const { colors } = useTheme();
|
||||||
transX.interpolate({
|
|
||||||
inputRange: [0, ACTION_WIDTH],
|
const animatedStyles = useAnimatedStyle(() => ({
|
||||||
outputRange: [-ACTION_WIDTH, 0]
|
transform: [{ translateX: transX.value }]
|
||||||
}),
|
}));
|
||||||
reverse
|
|
||||||
);
|
|
||||||
|
|
||||||
const isCondensed = displayMode === DisplayMode.Condensed;
|
const isCondensed = displayMode === DisplayMode.Condensed;
|
||||||
const viewHeight = isCondensed ? { height: ROW_HEIGHT_CONDENSED } : null;
|
const viewHeight = isCondensed ? { height: ROW_HEIGHT_CONDENSED } : null;
|
||||||
|
@ -29,20 +36,16 @@ export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleR
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
styles.actionLeftButtonContainer,
|
styles.actionLeftButtonContainer,
|
||||||
{
|
{ width: width * 2, backgroundColor: colors.tintColor, right: '100%' },
|
||||||
right: width - ACTION_WIDTH,
|
viewHeight,
|
||||||
width,
|
animatedStyles
|
||||||
transform: [{ translateX }],
|
|
||||||
backgroundColor: themes[theme].tintColor
|
|
||||||
},
|
|
||||||
viewHeight
|
|
||||||
]}>
|
]}>
|
||||||
<View style={[styles.actionLeftButtonContainer, viewHeight]}>
|
<View style={[styles.actionLeftButtonContainer, viewHeight]}>
|
||||||
<RectButton style={styles.actionButton} onPress={onToggleReadPress}>
|
<RectButton style={styles.actionButton} onPress={onToggleReadPress}>
|
||||||
<CustomIcon
|
<CustomIcon
|
||||||
size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
|
size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
|
||||||
name={isRead ? 'flag' : 'check'}
|
name={isRead ? 'flag' : 'check'}
|
||||||
color={themes[theme].buttonText}
|
color={colors.buttonText}
|
||||||
/>
|
/>
|
||||||
</RectButton>
|
</RectButton>
|
||||||
</View>
|
</View>
|
||||||
|
@ -51,64 +54,102 @@ export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleR
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RightActions = React.memo(
|
export const RightActions = React.memo(({ transX, favorite, width, toggleFav, onHidePress, displayMode }: IRightActionsProps) => {
|
||||||
({ transX, favorite, width, toggleFav, onHidePress, theme, displayMode }: IRightActionsProps) => {
|
const { colors } = useTheme();
|
||||||
const translateXFav = Animated.multiply(
|
|
||||||
transX.interpolate({
|
|
||||||
inputRange: [-width / 2, -ACTION_WIDTH * 2, 0],
|
|
||||||
outputRange: [width / 2, width - ACTION_WIDTH * 2, width]
|
|
||||||
}),
|
|
||||||
reverse
|
|
||||||
);
|
|
||||||
const translateXHide = Animated.multiply(
|
|
||||||
transX.interpolate({
|
|
||||||
inputRange: [-width, -LONG_SWIPE, -ACTION_WIDTH * 2, 0],
|
|
||||||
outputRange: [0, width - LONG_SWIPE, width - ACTION_WIDTH, width]
|
|
||||||
}),
|
|
||||||
reverse
|
|
||||||
);
|
|
||||||
|
|
||||||
const isCondensed = displayMode === DisplayMode.Condensed;
|
const animatedFavStyles = useAnimatedStyle(() => ({ transform: [{ translateX: transX.value }] }));
|
||||||
const viewHeight = isCondensed ? { height: ROW_HEIGHT_CONDENSED } : null;
|
|
||||||
|
|
||||||
return (
|
const translateXHide = useSharedValue(0);
|
||||||
<View style={[styles.actionsLeftContainer, viewHeight]} pointerEvents='box-none'>
|
|
||||||
<Animated.View
|
const triggerHideAnimation = (toValue: number) => {
|
||||||
style={[
|
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
||||||
styles.actionRightButtonContainer,
|
translateXHide.value = withSpring(toValue, { overshootClamping: true, mass: 0.7 });
|
||||||
{
|
};
|
||||||
width,
|
|
||||||
transform: [{ translateX: translateXFav }],
|
useAnimatedReaction(
|
||||||
backgroundColor: themes[theme].hideBackground
|
() => transX.value,
|
||||||
},
|
(currentTransX, previousTransX) => {
|
||||||
viewHeight
|
// Triggers the animation and hapticFeedback if swipe reaches/unreaches the threshold.
|
||||||
]}>
|
if (I18n.isRTL) {
|
||||||
<RectButton style={[styles.actionButton, { backgroundColor: themes[theme].favoriteBackground }]} onPress={toggleFav}>
|
if (previousTransX && currentTransX > LONG_SWIPE && previousTransX <= LONG_SWIPE) {
|
||||||
<CustomIcon
|
runOnJS(triggerHideAnimation)(ACTION_WIDTH);
|
||||||
size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
|
} else if (previousTransX && currentTransX <= LONG_SWIPE && previousTransX > LONG_SWIPE) {
|
||||||
name={favorite ? 'star-filled' : 'star'}
|
runOnJS(triggerHideAnimation)(0);
|
||||||
color={themes[theme].buttonText}
|
}
|
||||||
/>
|
} else if (previousTransX && currentTransX < -LONG_SWIPE && previousTransX >= -LONG_SWIPE) {
|
||||||
</RectButton>
|
runOnJS(triggerHideAnimation)(-ACTION_WIDTH);
|
||||||
</Animated.View>
|
} else if (previousTransX && currentTransX >= -LONG_SWIPE && previousTransX < -LONG_SWIPE) {
|
||||||
<Animated.View
|
runOnJS(triggerHideAnimation)(0);
|
||||||
style={[
|
}
|
||||||
styles.actionRightButtonContainer,
|
}
|
||||||
{
|
);
|
||||||
width,
|
|
||||||
transform: [{ translateX: translateXHide }]
|
const animatedHideStyles = useAnimatedStyle(() => {
|
||||||
},
|
if (I18n.isRTL) {
|
||||||
isCondensed && { height: ROW_HEIGHT_CONDENSED }
|
if (transX.value < LONG_SWIPE && transX.value >= 2 * ACTION_WIDTH) {
|
||||||
]}>
|
const parallaxSwipe = interpolate(
|
||||||
<RectButton style={[styles.actionButton, { backgroundColor: themes[theme].hideBackground }]} onPress={onHidePress}>
|
transX.value,
|
||||||
<CustomIcon
|
[2 * ACTION_WIDTH, LONG_SWIPE],
|
||||||
size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
|
[ACTION_WIDTH, ACTION_WIDTH + 0.1 * transX.value]
|
||||||
name='unread-on-top-disabled'
|
);
|
||||||
color={themes[theme].buttonText}
|
return { transform: [{ translateX: parallaxSwipe + translateXHide.value }] };
|
||||||
/>
|
}
|
||||||
</RectButton>
|
return { transform: [{ translateX: transX.value - ACTION_WIDTH + translateXHide.value }] };
|
||||||
</Animated.View>
|
}
|
||||||
</View>
|
if (transX.value > -LONG_SWIPE && transX.value <= -2 * ACTION_WIDTH) {
|
||||||
);
|
const parallaxSwipe = interpolate(
|
||||||
}
|
transX.value,
|
||||||
);
|
[-2 * ACTION_WIDTH, -LONG_SWIPE],
|
||||||
|
[-ACTION_WIDTH, -ACTION_WIDTH + 0.1 * transX.value]
|
||||||
|
);
|
||||||
|
return { transform: [{ translateX: parallaxSwipe + translateXHide.value }] };
|
||||||
|
}
|
||||||
|
return { transform: [{ translateX: transX.value + ACTION_WIDTH + translateXHide.value }] };
|
||||||
|
});
|
||||||
|
|
||||||
|
const isCondensed = displayMode === DisplayMode.Condensed;
|
||||||
|
const viewHeight = isCondensed ? { height: ROW_HEIGHT_CONDENSED } : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.actionsLeftContainer, viewHeight]} pointerEvents='box-none'>
|
||||||
|
<Animated.View
|
||||||
|
style={[
|
||||||
|
styles.actionRightButtonContainer,
|
||||||
|
{
|
||||||
|
width,
|
||||||
|
backgroundColor: colors.favoriteBackground,
|
||||||
|
left: '100%'
|
||||||
|
},
|
||||||
|
viewHeight,
|
||||||
|
animatedFavStyles
|
||||||
|
]}>
|
||||||
|
<RectButton style={[styles.actionButton, { backgroundColor: colors.favoriteBackground }]} onPress={toggleFav}>
|
||||||
|
<CustomIcon
|
||||||
|
size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
|
||||||
|
name={favorite ? 'star-filled' : 'star'}
|
||||||
|
color={colors.buttonText}
|
||||||
|
/>
|
||||||
|
</RectButton>
|
||||||
|
</Animated.View>
|
||||||
|
<Animated.View
|
||||||
|
style={[
|
||||||
|
styles.actionRightButtonContainer,
|
||||||
|
{
|
||||||
|
width: width * 2,
|
||||||
|
backgroundColor: colors.hideBackground,
|
||||||
|
left: '100%'
|
||||||
|
},
|
||||||
|
isCondensed && { height: ROW_HEIGHT_CONDENSED },
|
||||||
|
animatedHideStyles
|
||||||
|
]}>
|
||||||
|
<RectButton style={[styles.actionButton, { backgroundColor: colors.hideBackground }]} onPress={onHidePress}>
|
||||||
|
<CustomIcon
|
||||||
|
size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
|
||||||
|
name='unread-on-top-disabled'
|
||||||
|
color={colors.buttonText}
|
||||||
|
/>
|
||||||
|
</RectButton>
|
||||||
|
</Animated.View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
|
@ -66,7 +66,6 @@ const RoomItem = ({
|
||||||
hideChannel={hideChannel}
|
hideChannel={hideChannel}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
type={type}
|
type={type}
|
||||||
theme={theme}
|
|
||||||
isFocused={isFocused}
|
isFocused={isFocused}
|
||||||
swipeEnabled={swipeEnabled}
|
swipeEnabled={swipeEnabled}
|
||||||
displayMode={displayMode}>
|
displayMode={displayMode}>
|
||||||
|
|
|
@ -1,207 +1,98 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Animated } from 'react-native';
|
import Animated, {
|
||||||
|
useAnimatedGestureHandler,
|
||||||
|
useSharedValue,
|
||||||
|
useAnimatedStyle,
|
||||||
|
withSpring,
|
||||||
|
runOnJS
|
||||||
|
} from 'react-native-reanimated';
|
||||||
import {
|
import {
|
||||||
GestureEvent,
|
|
||||||
HandlerStateChangeEventPayload,
|
|
||||||
LongPressGestureHandler,
|
LongPressGestureHandler,
|
||||||
PanGestureHandler,
|
PanGestureHandler,
|
||||||
PanGestureHandlerEventPayload,
|
State,
|
||||||
State
|
HandlerStateChangeEventPayload,
|
||||||
|
PanGestureHandlerEventPayload
|
||||||
} from 'react-native-gesture-handler';
|
} from 'react-native-gesture-handler';
|
||||||
|
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import { ACTION_WIDTH, LONG_SWIPE, SMALL_SWIPE } from './styles';
|
import { ACTION_WIDTH, LONG_SWIPE, SMALL_SWIPE } from './styles';
|
||||||
import { isRTL } from '../../i18n';
|
|
||||||
import { themes } from '../../lib/constants';
|
|
||||||
import { LeftActions, RightActions } from './Actions';
|
import { LeftActions, RightActions } from './Actions';
|
||||||
import { ITouchableProps } from './interfaces';
|
import { ITouchableProps } from './interfaces';
|
||||||
|
import { useTheme } from '../../theme';
|
||||||
|
import I18n from '../../i18n';
|
||||||
|
|
||||||
class Touchable extends React.Component<ITouchableProps, any> {
|
const Touchable = ({
|
||||||
private dragX: Animated.Value;
|
children,
|
||||||
private rowOffSet: Animated.Value;
|
type,
|
||||||
private reverse: Animated.Value;
|
onPress,
|
||||||
private transX: Animated.AnimatedAddition;
|
onLongPress,
|
||||||
private transXReverse: Animated.AnimatedMultiplication;
|
testID,
|
||||||
private _onGestureEvent: (event: GestureEvent<PanGestureHandlerEventPayload>) => void;
|
width,
|
||||||
private _value: number;
|
favorite,
|
||||||
|
isRead,
|
||||||
|
rid,
|
||||||
|
toggleFav,
|
||||||
|
toggleRead,
|
||||||
|
hideChannel,
|
||||||
|
isFocused,
|
||||||
|
swipeEnabled,
|
||||||
|
displayMode
|
||||||
|
}: ITouchableProps): React.ReactElement => {
|
||||||
|
const { theme, colors } = useTheme();
|
||||||
|
|
||||||
constructor(props: ITouchableProps) {
|
const rowOffSet = useSharedValue(0);
|
||||||
super(props);
|
const transX = useSharedValue(0);
|
||||||
this.dragX = new Animated.Value(0);
|
const rowState = useSharedValue(0); // 0: closed, 1: right opened, -1: left opened
|
||||||
this.rowOffSet = new Animated.Value(0);
|
let _value = 0;
|
||||||
this.reverse = new Animated.Value(isRTL() ? -1 : 1);
|
|
||||||
this.transX = Animated.add(this.rowOffSet, this.dragX);
|
|
||||||
this.transXReverse = Animated.multiply(this.transX, this.reverse);
|
|
||||||
this.state = {
|
|
||||||
rowState: 0 // 0: closed, 1: right opened, -1: left opened
|
|
||||||
};
|
|
||||||
this._onGestureEvent = Animated.event([{ nativeEvent: { translationX: this.dragX } }], { useNativeDriver: true });
|
|
||||||
this._value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onHandlerStateChange = ({ nativeEvent }: { nativeEvent: HandlerStateChangeEventPayload & PanGestureHandlerEventPayload }) => {
|
const close = () => {
|
||||||
if (nativeEvent.oldState === State.ACTIVE) {
|
rowState.value = 0;
|
||||||
this._handleRelease(nativeEvent);
|
transX.value = withSpring(0, { overshootClamping: true });
|
||||||
}
|
rowOffSet.value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
onLongPressHandlerStateChange = ({ nativeEvent }: { nativeEvent: HandlerStateChangeEventPayload }) => {
|
const handleToggleFav = () => {
|
||||||
if (nativeEvent.state === State.ACTIVE) {
|
|
||||||
this.onLongPress();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleRelease = (nativeEvent: PanGestureHandlerEventPayload) => {
|
|
||||||
const { translationX } = nativeEvent;
|
|
||||||
const { rowState } = this.state;
|
|
||||||
this._value += translationX;
|
|
||||||
|
|
||||||
let toValue = 0;
|
|
||||||
if (rowState === 0) {
|
|
||||||
// if no option is opened
|
|
||||||
if (translationX > 0 && translationX < LONG_SWIPE) {
|
|
||||||
// open leading option if he swipe right but not enough to trigger action
|
|
||||||
if (isRTL()) {
|
|
||||||
toValue = 2 * ACTION_WIDTH;
|
|
||||||
} else {
|
|
||||||
toValue = ACTION_WIDTH;
|
|
||||||
}
|
|
||||||
this.setState({ rowState: -1 });
|
|
||||||
} else if (translationX >= LONG_SWIPE) {
|
|
||||||
toValue = 0;
|
|
||||||
if (isRTL()) {
|
|
||||||
this.hideChannel();
|
|
||||||
} else {
|
|
||||||
this.toggleRead();
|
|
||||||
}
|
|
||||||
} else if (translationX < 0 && translationX > -LONG_SWIPE) {
|
|
||||||
// open trailing option if he swipe left
|
|
||||||
if (isRTL()) {
|
|
||||||
toValue = -ACTION_WIDTH;
|
|
||||||
} else {
|
|
||||||
toValue = -2 * ACTION_WIDTH;
|
|
||||||
}
|
|
||||||
this.setState({ rowState: 1 });
|
|
||||||
} else if (translationX <= -LONG_SWIPE) {
|
|
||||||
toValue = 0;
|
|
||||||
this.setState({ rowState: 0 });
|
|
||||||
if (isRTL()) {
|
|
||||||
this.toggleRead();
|
|
||||||
} else {
|
|
||||||
this.hideChannel();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toValue = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rowState === -1) {
|
|
||||||
// if left option is opened
|
|
||||||
if (this._value < SMALL_SWIPE) {
|
|
||||||
toValue = 0;
|
|
||||||
this.setState({ rowState: 0 });
|
|
||||||
} else if (this._value > LONG_SWIPE) {
|
|
||||||
toValue = 0;
|
|
||||||
this.setState({ rowState: 0 });
|
|
||||||
if (isRTL()) {
|
|
||||||
this.hideChannel();
|
|
||||||
} else {
|
|
||||||
this.toggleRead();
|
|
||||||
}
|
|
||||||
} else if (isRTL()) {
|
|
||||||
toValue = 2 * ACTION_WIDTH;
|
|
||||||
} else {
|
|
||||||
toValue = ACTION_WIDTH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rowState === 1) {
|
|
||||||
// if right option is opened
|
|
||||||
if (this._value > -2 * SMALL_SWIPE) {
|
|
||||||
toValue = 0;
|
|
||||||
this.setState({ rowState: 0 });
|
|
||||||
} else if (this._value < -LONG_SWIPE) {
|
|
||||||
toValue = 0;
|
|
||||||
this.setState({ rowState: 0 });
|
|
||||||
if (isRTL()) {
|
|
||||||
this.toggleRead();
|
|
||||||
} else {
|
|
||||||
this.hideChannel();
|
|
||||||
}
|
|
||||||
} else if (isRTL()) {
|
|
||||||
toValue = -ACTION_WIDTH;
|
|
||||||
} else {
|
|
||||||
toValue = -2 * ACTION_WIDTH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._animateRow(toValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
_animateRow = (toValue: number) => {
|
|
||||||
this.rowOffSet.setValue(this._value);
|
|
||||||
this._value = toValue;
|
|
||||||
this.dragX.setValue(0);
|
|
||||||
Animated.spring(this.rowOffSet, {
|
|
||||||
toValue,
|
|
||||||
bounciness: 0,
|
|
||||||
useNativeDriver: true
|
|
||||||
}).start();
|
|
||||||
};
|
|
||||||
|
|
||||||
close = () => {
|
|
||||||
this.setState({ rowState: 0 });
|
|
||||||
this._animateRow(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
toggleFav = () => {
|
|
||||||
const { toggleFav, rid, favorite } = this.props;
|
|
||||||
if (toggleFav) {
|
if (toggleFav) {
|
||||||
toggleFav(rid, favorite);
|
toggleFav(rid, favorite);
|
||||||
}
|
}
|
||||||
this.close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleRead = () => {
|
const handleToggleRead = () => {
|
||||||
const { toggleRead, rid, isRead } = this.props;
|
|
||||||
if (toggleRead) {
|
if (toggleRead) {
|
||||||
toggleRead(rid, isRead);
|
toggleRead(rid, isRead);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
hideChannel = () => {
|
const handleHideChannel = () => {
|
||||||
const { hideChannel, rid, type } = this.props;
|
|
||||||
if (hideChannel) {
|
if (hideChannel) {
|
||||||
hideChannel(rid, type);
|
hideChannel(rid, type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onToggleReadPress = () => {
|
const onToggleReadPress = () => {
|
||||||
this.toggleRead();
|
handleToggleRead();
|
||||||
this.close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
onHidePress = () => {
|
const onHidePress = () => {
|
||||||
this.hideChannel();
|
handleHideChannel();
|
||||||
this.close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
onPress = () => {
|
const handlePress = () => {
|
||||||
const { rowState } = this.state;
|
if (rowState.value !== 0) {
|
||||||
if (rowState !== 0) {
|
close();
|
||||||
this.close();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { onPress } = this.props;
|
|
||||||
if (onPress) {
|
if (onPress) {
|
||||||
onPress();
|
onPress();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onLongPress = () => {
|
const handleLongPress = () => {
|
||||||
const { rowState } = this.state;
|
if (rowState.value !== 0) {
|
||||||
const { onLongPress } = this.props;
|
close();
|
||||||
if (rowState !== 0) {
|
|
||||||
this.close();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,55 +101,139 @@ class Touchable extends React.Component<ITouchableProps, any> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
const onLongPressHandlerStateChange = ({ nativeEvent }: { nativeEvent: HandlerStateChangeEventPayload }) => {
|
||||||
const { testID, isRead, width, favorite, children, theme, isFocused, swipeEnabled, displayMode } = this.props;
|
if (nativeEvent.state === State.ACTIVE) {
|
||||||
|
handleLongPress();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
const handleRelease = (event: PanGestureHandlerEventPayload) => {
|
||||||
<LongPressGestureHandler onHandlerStateChange={this.onLongPressHandlerStateChange}>
|
const { translationX } = event;
|
||||||
<Animated.View>
|
_value += translationX;
|
||||||
<PanGestureHandler
|
let toValue = 0;
|
||||||
minDeltaX={20}
|
if (rowState.value === 0) {
|
||||||
onGestureEvent={this._onGestureEvent}
|
// if no option is opened
|
||||||
onHandlerStateChange={this._onHandlerStateChange}
|
if (translationX > 0 && translationX < LONG_SWIPE) {
|
||||||
enabled={swipeEnabled}>
|
if (I18n.isRTL) {
|
||||||
<Animated.View>
|
toValue = 2 * ACTION_WIDTH;
|
||||||
<LeftActions
|
} else {
|
||||||
transX={this.transXReverse}
|
toValue = ACTION_WIDTH;
|
||||||
isRead={isRead}
|
}
|
||||||
width={width}
|
rowState.value = -1;
|
||||||
onToggleReadPress={this.onToggleReadPress}
|
} else if (translationX >= LONG_SWIPE) {
|
||||||
|
toValue = 0;
|
||||||
|
if (I18n.isRTL) {
|
||||||
|
handleHideChannel();
|
||||||
|
} else {
|
||||||
|
handleToggleRead();
|
||||||
|
}
|
||||||
|
} else if (translationX < 0 && translationX > -LONG_SWIPE) {
|
||||||
|
// open trailing option if he swipe left
|
||||||
|
if (I18n.isRTL) {
|
||||||
|
toValue = -ACTION_WIDTH;
|
||||||
|
} else {
|
||||||
|
toValue = -2 * ACTION_WIDTH;
|
||||||
|
}
|
||||||
|
rowState.value = 1;
|
||||||
|
} else if (translationX <= -LONG_SWIPE) {
|
||||||
|
toValue = 0;
|
||||||
|
rowState.value = 1;
|
||||||
|
if (I18n.isRTL) {
|
||||||
|
handleToggleRead();
|
||||||
|
} else {
|
||||||
|
handleHideChannel();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toValue = 0;
|
||||||
|
}
|
||||||
|
} else if (rowState.value === -1) {
|
||||||
|
// if left option is opened
|
||||||
|
if (_value < SMALL_SWIPE) {
|
||||||
|
toValue = 0;
|
||||||
|
rowState.value = 0;
|
||||||
|
} else if (_value > LONG_SWIPE) {
|
||||||
|
toValue = 0;
|
||||||
|
rowState.value = 0;
|
||||||
|
if (I18n.isRTL) {
|
||||||
|
handleHideChannel();
|
||||||
|
} else {
|
||||||
|
handleToggleRead();
|
||||||
|
}
|
||||||
|
} else if (I18n.isRTL) {
|
||||||
|
toValue = 2 * ACTION_WIDTH;
|
||||||
|
} else {
|
||||||
|
toValue = ACTION_WIDTH;
|
||||||
|
}
|
||||||
|
} else if (rowState.value === 1) {
|
||||||
|
// if right option is opened
|
||||||
|
if (_value > -2 * SMALL_SWIPE) {
|
||||||
|
toValue = 0;
|
||||||
|
rowState.value = 0;
|
||||||
|
} else if (_value < -LONG_SWIPE) {
|
||||||
|
if (I18n.isRTL) {
|
||||||
|
handleToggleRead();
|
||||||
|
} else {
|
||||||
|
handleHideChannel();
|
||||||
|
}
|
||||||
|
} else if (I18n.isRTL) {
|
||||||
|
toValue = -ACTION_WIDTH;
|
||||||
|
} else {
|
||||||
|
toValue = -2 * ACTION_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transX.value = withSpring(toValue, { overshootClamping: true });
|
||||||
|
rowOffSet.value = toValue;
|
||||||
|
_value = toValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onGestureEvent = useAnimatedGestureHandler({
|
||||||
|
onActive: event => {
|
||||||
|
transX.value = event.translationX + rowOffSet.value;
|
||||||
|
if (transX.value > 2 * width) transX.value = 2 * width;
|
||||||
|
},
|
||||||
|
onEnd: event => {
|
||||||
|
runOnJS(handleRelease)(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const animatedStyles = useAnimatedStyle(() => ({ transform: [{ translateX: transX.value }] }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LongPressGestureHandler onHandlerStateChange={onLongPressHandlerStateChange}>
|
||||||
|
<Animated.View>
|
||||||
|
<PanGestureHandler activeOffsetX={[-20, 20]} onGestureEvent={onGestureEvent} enabled={swipeEnabled}>
|
||||||
|
<Animated.View>
|
||||||
|
<LeftActions
|
||||||
|
transX={transX}
|
||||||
|
isRead={isRead}
|
||||||
|
width={width}
|
||||||
|
onToggleReadPress={onToggleReadPress}
|
||||||
|
displayMode={displayMode}
|
||||||
|
/>
|
||||||
|
<RightActions
|
||||||
|
transX={transX}
|
||||||
|
favorite={favorite}
|
||||||
|
width={width}
|
||||||
|
toggleFav={handleToggleFav}
|
||||||
|
onHidePress={onHidePress}
|
||||||
|
displayMode={displayMode}
|
||||||
|
/>
|
||||||
|
<Animated.View style={animatedStyles}>
|
||||||
|
<Touch
|
||||||
|
onPress={handlePress}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
displayMode={displayMode}
|
testID={testID}
|
||||||
/>
|
|
||||||
<RightActions
|
|
||||||
transX={this.transXReverse}
|
|
||||||
favorite={favorite}
|
|
||||||
width={width}
|
|
||||||
toggleFav={this.toggleFav}
|
|
||||||
onHidePress={this.onHidePress}
|
|
||||||
theme={theme}
|
|
||||||
displayMode={displayMode}
|
|
||||||
/>
|
|
||||||
<Animated.View
|
|
||||||
style={{
|
style={{
|
||||||
transform: [{ translateX: this.transX }]
|
backgroundColor: isFocused ? colors.chatComponentBackground : colors.backgroundColor
|
||||||
}}>
|
}}>
|
||||||
<Touch
|
{children}
|
||||||
onPress={this.onPress}
|
</Touch>
|
||||||
theme={theme}
|
|
||||||
testID={testID}
|
|
||||||
style={{
|
|
||||||
backgroundColor: isFocused ? themes[theme].chatComponentBackground : themes[theme].backgroundColor
|
|
||||||
}}>
|
|
||||||
{children}
|
|
||||||
</Touch>
|
|
||||||
</Animated.View>
|
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</PanGestureHandler>
|
</Animated.View>
|
||||||
</Animated.View>
|
</PanGestureHandler>
|
||||||
</LongPressGestureHandler>
|
</Animated.View>
|
||||||
);
|
</LongPressGestureHandler>
|
||||||
}
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Touchable;
|
export default Touchable;
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Animated } from 'react-native';
|
import Animated from 'react-native-reanimated';
|
||||||
|
|
||||||
import { TSupportedThemes } from '../../theme';
|
import { TSupportedThemes } from '../../theme';
|
||||||
import { TUserStatus, ILastMessage, SubscriptionType, IOmnichannelSource } from '../../definitions';
|
import { TUserStatus, ILastMessage, SubscriptionType, IOmnichannelSource } from '../../definitions';
|
||||||
|
|
||||||
export interface ILeftActionsProps {
|
export interface ILeftActionsProps {
|
||||||
theme: TSupportedThemes;
|
transX: Animated.SharedValue<number>;
|
||||||
transX: Animated.AnimatedAddition | Animated.AnimatedMultiplication;
|
|
||||||
isRead: boolean;
|
isRead: boolean;
|
||||||
width: number;
|
width: number;
|
||||||
onToggleReadPress(): void;
|
onToggleReadPress(): void;
|
||||||
|
@ -14,8 +13,7 @@ export interface ILeftActionsProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRightActionsProps {
|
export interface IRightActionsProps {
|
||||||
theme: TSupportedThemes;
|
transX: Animated.SharedValue<number>;
|
||||||
transX: Animated.AnimatedAddition | Animated.AnimatedMultiplication;
|
|
||||||
favorite: boolean;
|
favorite: boolean;
|
||||||
width: number;
|
width: number;
|
||||||
toggleFav(): void;
|
toggleFav(): void;
|
||||||
|
@ -159,7 +157,6 @@ export interface ITouchableProps {
|
||||||
toggleFav: Function;
|
toggleFav: Function;
|
||||||
toggleRead: Function;
|
toggleRead: Function;
|
||||||
hideChannel: Function;
|
hideChannel: Function;
|
||||||
theme: TSupportedThemes;
|
|
||||||
isFocused: boolean;
|
isFocused: boolean;
|
||||||
swipeEnabled: boolean;
|
swipeEnabled: boolean;
|
||||||
displayMode: string;
|
displayMode: string;
|
||||||
|
|
|
@ -6,7 +6,7 @@ export const ROW_HEIGHT = 75 * PixelRatio.getFontScale();
|
||||||
export const ROW_HEIGHT_CONDENSED = 60 * PixelRatio.getFontScale();
|
export const ROW_HEIGHT_CONDENSED = 60 * PixelRatio.getFontScale();
|
||||||
export const ACTION_WIDTH = 80;
|
export const ACTION_WIDTH = 80;
|
||||||
export const SMALL_SWIPE = ACTION_WIDTH / 2;
|
export const SMALL_SWIPE = ACTION_WIDTH / 2;
|
||||||
export const LONG_SWIPE = ACTION_WIDTH * 3;
|
export const LONG_SWIPE = ACTION_WIDTH * 2.5;
|
||||||
|
|
||||||
export default StyleSheet.create({
|
export default StyleSheet.create({
|
||||||
flex: {
|
flex: {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { KeyCommandsEmitter } from 'react-native-keycommands';
|
||||||
import { initialWindowMetrics, SafeAreaProvider } from 'react-native-safe-area-context';
|
import { initialWindowMetrics, SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
import RNScreens from 'react-native-screens';
|
import RNScreens from 'react-native-screens';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
import { appInit, appInitLocalSettings, setMasterDetail as setMasterDetailAction } from './actions/app';
|
import { appInit, appInitLocalSettings, setMasterDetail as setMasterDetailAction } from './actions/app';
|
||||||
import { deepLinkingOpen } from './actions/deepLinking';
|
import { deepLinkingOpen } from './actions/deepLinking';
|
||||||
|
@ -224,14 +225,16 @@ export default class Root extends React.Component<{}, IState> {
|
||||||
fontScale,
|
fontScale,
|
||||||
setDimensions: this.setDimensions
|
setDimensions: this.setDimensions
|
||||||
}}>
|
}}>
|
||||||
<ActionSheetProvider>
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||||
<AppContainer />
|
<ActionSheetProvider>
|
||||||
<TwoFactor />
|
<AppContainer />
|
||||||
<ScreenLockedView />
|
<TwoFactor />
|
||||||
<ChangePasscodeView />
|
<ScreenLockedView />
|
||||||
<InAppNotification />
|
<ChangePasscodeView />
|
||||||
<Toast />
|
<InAppNotification />
|
||||||
</ActionSheetProvider>
|
<Toast />
|
||||||
|
</ActionSheetProvider>
|
||||||
|
</GestureHandlerRootView>
|
||||||
</DimensionsContext.Provider>
|
</DimensionsContext.Provider>
|
||||||
</ThemeContext.Provider>
|
</ThemeContext.Provider>
|
||||||
</Provider>
|
</Provider>
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { IUser } from '../../definitions';
|
||||||
import sdk from '../services/sdk';
|
import sdk from '../services/sdk';
|
||||||
import { compareServerVersion } from './helpers/compareServerVersion';
|
import { compareServerVersion } from './helpers/compareServerVersion';
|
||||||
|
|
||||||
export const _activeUsersSubTimeout: { activeUsersSubTimeout: boolean | ReturnType<typeof setTimeout> } = {
|
export const _activeUsersSubTimeout: { activeUsersSubTimeout: boolean | ReturnType<typeof setTimeout> | number } = {
|
||||||
activeUsersSubTimeout: false
|
activeUsersSubTimeout: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ const WINDOW_TIME = 1000;
|
||||||
export default class RoomSubscription {
|
export default class RoomSubscription {
|
||||||
private rid: string;
|
private rid: string;
|
||||||
private isAlive: boolean;
|
private isAlive: boolean;
|
||||||
private timer: null | number;
|
private timer: ReturnType<typeof setTimeout> | null;
|
||||||
private queue: { [key: string]: IMessage };
|
private queue: { [key: string]: IMessage };
|
||||||
private messagesBatch: {};
|
private messagesBatch: {};
|
||||||
private _messagesBatch: { [key: string]: TMessageModel };
|
private _messagesBatch: { [key: string]: TMessageModel };
|
||||||
|
|
|
@ -41,7 +41,7 @@ const removeListener = (listener: { stop: () => void }) => listener.stop();
|
||||||
let streamListener: Promise<any> | false;
|
let streamListener: Promise<any> | false;
|
||||||
let subServer: string;
|
let subServer: string;
|
||||||
let queue: { [key: string]: ISubscription | IRoom } = {};
|
let queue: { [key: string]: ISubscription | IRoom } = {};
|
||||||
let subTimer: number | null | false = null;
|
let subTimer: ReturnType<typeof setTimeout> | null | false = null;
|
||||||
const WINDOW_TIME = 500;
|
const WINDOW_TIME = 500;
|
||||||
|
|
||||||
export let roomsSubscription: { stop: () => void } | null = null;
|
export let roomsSubscription: { stop: () => void } | null = null;
|
||||||
|
|
|
@ -12,6 +12,7 @@ export default function debounce(func: Function, wait?: number, immediate?: bool
|
||||||
};
|
};
|
||||||
const callNow = immediate && !timeout;
|
const callNow = immediate && !timeout;
|
||||||
clearTimeout(timeout!);
|
clearTimeout(timeout!);
|
||||||
|
// @ts-ignore
|
||||||
timeout = setTimeout(later, wait);
|
timeout = setTimeout(later, wait);
|
||||||
if (callNow) {
|
if (callNow) {
|
||||||
func.apply(context, args);
|
func.apply(context, args);
|
||||||
|
|
|
@ -69,7 +69,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
|
||||||
private viewabilityConfig = {
|
private viewabilityConfig = {
|
||||||
itemVisiblePercentThreshold: 10
|
itemVisiblePercentThreshold: 10
|
||||||
};
|
};
|
||||||
private highlightedMessageTimeout: number | undefined | false;
|
private highlightedMessageTimeout: ReturnType<typeof setTimeout> | undefined | false;
|
||||||
private thread?: TThreadModel;
|
private thread?: TThreadModel;
|
||||||
private messagesObservable?: Observable<TMessageModel[] | TThreadMessageModel[]>;
|
private messagesObservable?: Observable<TMessageModel[] | TThreadMessageModel[]>;
|
||||||
private messagesSubscription?: Subscription;
|
private messagesSubscription?: Subscription;
|
||||||
|
|
|
@ -197,9 +197,9 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
private subSubscription?: Subscription;
|
private subSubscription?: Subscription;
|
||||||
private queryUnreads?: Subscription;
|
private queryUnreads?: Subscription;
|
||||||
private retryInit = 0;
|
private retryInit = 0;
|
||||||
private retryInitTimeout?: number;
|
private retryInitTimeout?: ReturnType<typeof setTimeout>;
|
||||||
private retryFindCount = 0;
|
private retryFindCount = 0;
|
||||||
private retryFindTimeout?: number;
|
private retryFindTimeout?: ReturnType<typeof setTimeout>;
|
||||||
private messageErrorActions?: IMessageErrorActions | null;
|
private messageErrorActions?: IMessageErrorActions | null;
|
||||||
private messageActions?: IMessageActions | null;
|
private messageActions?: IMessageActions | null;
|
||||||
// Type of InteractionManager.runAfterInteractions
|
// Type of InteractionManager.runAfterInteractions
|
||||||
|
|
|
@ -536,7 +536,7 @@ PODS:
|
||||||
- RNFBApp
|
- RNFBApp
|
||||||
- RNFileViewer (2.1.5):
|
- RNFileViewer (2.1.5):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNGestureHandler (1.10.3):
|
- RNGestureHandler (2.4.2):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNImageCropPicker (0.36.3):
|
- RNImageCropPicker (0.36.3):
|
||||||
- React-Core
|
- React-Core
|
||||||
|
@ -961,7 +961,7 @@ SPEC CHECKSUMS:
|
||||||
EXVideoThumbnails: 442c3abadb51a81551a3b53705b7560de390e6f7
|
EXVideoThumbnails: 442c3abadb51a81551a3b53705b7560de390e6f7
|
||||||
EXWebBrowser: 76783ba5dcb8699237746ecf41a9643d428a4cc5
|
EXWebBrowser: 76783ba5dcb8699237746ecf41a9643d428a4cc5
|
||||||
FBLazyVector: c9b6dfcde9b3d497793c40d4ccbfbfb05092e0df
|
FBLazyVector: c9b6dfcde9b3d497793c40d4ccbfbfb05092e0df
|
||||||
FBReactNativeSpec: addc4f0e6ab00dc628fe91de8bfca4601762673a
|
FBReactNativeSpec: c39f7fc0cd6cc64f0a2a5beffc64b1aa5d42740e
|
||||||
Firebase: 919186c8e119dd9372a45fd1dd17a8a942bc1892
|
Firebase: 919186c8e119dd9372a45fd1dd17a8a942bc1892
|
||||||
FirebaseAnalytics: 5fa308e1b13f838d0f6dc74719ac2a72e8c5afc4
|
FirebaseAnalytics: 5fa308e1b13f838d0f6dc74719ac2a72e8c5afc4
|
||||||
FirebaseCore: 8cd4f8ea22075e0ee582849b1cf79d8816506085
|
FirebaseCore: 8cd4f8ea22075e0ee582849b1cf79d8816506085
|
||||||
|
@ -1046,7 +1046,7 @@ SPEC CHECKSUMS:
|
||||||
RNFBApp: 6fd8a7e757135d4168bf033a8812c241af7363a0
|
RNFBApp: 6fd8a7e757135d4168bf033a8812c241af7363a0
|
||||||
RNFBCrashlytics: 88de72c2476b5868a892d9523b89b86c527c540e
|
RNFBCrashlytics: 88de72c2476b5868a892d9523b89b86c527c540e
|
||||||
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
|
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
|
||||||
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
|
RNGestureHandler: 61628a2c859172551aa2100d3e73d1e57878392f
|
||||||
RNImageCropPicker: 97289cd94fb01ab79db4e5c92938be4d0d63415d
|
RNImageCropPicker: 97289cd94fb01ab79db4e5c92938be4d0d63415d
|
||||||
RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b
|
RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b
|
||||||
RNReanimated: 241c586663f44f19a53883c63375fdd041253960
|
RNReanimated: 241c586663f44f19a53883c63375fdd041253960
|
||||||
|
|
|
@ -1870,7 +1870,7 @@
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386";
|
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
@ -1925,7 +1925,7 @@
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386";
|
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import mockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock.js';
|
import mockClipboard from '@react-native-clipboard/clipboard/jest/clipboard-mock.js';
|
||||||
|
|
||||||
|
require('react-native-reanimated/lib/reanimated2/jestUtils').setUpTests();
|
||||||
|
|
||||||
jest.mock('@react-native-clipboard/clipboard', () => mockClipboard);
|
jest.mock('@react-native-clipboard/clipboard', () => mockClipboard);
|
||||||
|
|
||||||
jest.mock('react-native-mmkv-storage', () => ({
|
jest.mock('react-native-mmkv-storage', () => ({
|
||||||
|
@ -30,4 +32,6 @@ jest.mock('react-native-file-viewer', () => ({
|
||||||
open: jest.fn(() => null)
|
open: jest.fn(() => null)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock('expo-haptics', () => jest.fn(() => null));
|
||||||
|
|
||||||
jest.mock('./app/lib/database', () => jest.fn(() => null));
|
jest.mock('./app/lib/database', () => jest.fn(() => null));
|
||||||
|
|
|
@ -90,8 +90,8 @@
|
||||||
"react-native-easy-grid": "^0.2.2",
|
"react-native-easy-grid": "^0.2.2",
|
||||||
"react-native-easy-toast": "^1.2.0",
|
"react-native-easy-toast": "^1.2.0",
|
||||||
"react-native-fast-image": "RocketChat/react-native-fast-image.git#bump-version",
|
"react-native-fast-image": "RocketChat/react-native-fast-image.git#bump-version",
|
||||||
"react-native-file-viewer": "^2.1.5",
|
"react-native-file-viewer": "^2.1.4",
|
||||||
"react-native-gesture-handler": "^1.10.3",
|
"react-native-gesture-handler": "2.4.2",
|
||||||
"react-native-image-crop-picker": "RocketChat/react-native-image-crop-picker",
|
"react-native-image-crop-picker": "RocketChat/react-native-image-crop-picker",
|
||||||
"react-native-image-progress": "^1.1.1",
|
"react-native-image-progress": "^1.1.1",
|
||||||
"react-native-jitsi-meet": "RocketChat/react-native-jitsi-meet",
|
"react-native-jitsi-meet": "RocketChat/react-native-jitsi-meet",
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||||
import { Dimensions, ScrollView } from 'react-native';
|
import { Dimensions, ScrollView } from 'react-native';
|
||||||
import { storiesOf } from '@storybook/react-native';
|
import { storiesOf } from '@storybook/react-native';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
import RoomItemComponent from '../../app/containers/RoomItem/RoomItem';
|
import RoomItemComponent from '../../app/containers/RoomItem/RoomItem';
|
||||||
import { longText } from '../utils';
|
import { longText } from '../utils';
|
||||||
|
@ -39,6 +40,7 @@ const RoomItem = props => (
|
||||||
|
|
||||||
const stories = storiesOf('Room Item', module)
|
const stories = storiesOf('Room Item', module)
|
||||||
.addDecorator(story => <Provider store={store}>{story()}</Provider>)
|
.addDecorator(story => <Provider store={store}>{story()}</Provider>)
|
||||||
|
.addDecorator(story => <SafeAreaProvider>{story()}</SafeAreaProvider>)
|
||||||
.addDecorator(story => <ScrollView style={{ backgroundColor: themes[_theme].backgroundColor }}>{story()}</ScrollView>);
|
.addDecorator(story => <ScrollView style={{ backgroundColor: themes[_theme].backgroundColor }}>{story()}</ScrollView>);
|
||||||
|
|
||||||
stories.add('Basic', () => <RoomItem />);
|
stories.add('Basic', () => <RoomItem />);
|
||||||
|
|
File diff suppressed because one or more lines are too long
20
yarn.lock
20
yarn.lock
|
@ -4525,9 +4525,9 @@
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/hammerjs@^2.0.36":
|
"@types/hammerjs@^2.0.36":
|
||||||
version "2.0.36"
|
version "2.0.41"
|
||||||
resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.36.tgz#17ce0a235e9ffbcdcdf5095646b374c2bf615a4c"
|
resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.41.tgz#f6ecf57d1b12d2befcce00e928a6a097c22980aa"
|
||||||
integrity sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ==
|
integrity sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA==
|
||||||
|
|
||||||
"@types/history@*":
|
"@types/history@*":
|
||||||
version "4.7.6"
|
version "4.7.6"
|
||||||
|
@ -12398,7 +12398,7 @@ lodash.truncate@^4.4.2:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||||
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
||||||
|
|
||||||
lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.5, lodash@^4.7.0:
|
lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5, lodash@^4.7.0:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
@ -14963,7 +14963,7 @@ react-native-fast-image@RocketChat/react-native-fast-image.git#bump-version:
|
||||||
version "8.5.12"
|
version "8.5.12"
|
||||||
resolved "https://codeload.github.com/RocketChat/react-native-fast-image/tar.gz/8bdb187a4500e23ad1c95324a669c25361bbf685"
|
resolved "https://codeload.github.com/RocketChat/react-native-fast-image/tar.gz/8bdb187a4500e23ad1c95324a669c25361bbf685"
|
||||||
|
|
||||||
react-native-file-viewer@^2.1.5:
|
react-native-file-viewer@^2.1.4:
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-file-viewer/-/react-native-file-viewer-2.1.5.tgz#cd4544f573108e79002b5c7e1ebfce4371885250"
|
resolved "https://registry.yarnpkg.com/react-native-file-viewer/-/react-native-file-viewer-2.1.5.tgz#cd4544f573108e79002b5c7e1ebfce4371885250"
|
||||||
integrity sha512-MGC6sx9jsqHdefhVQ6o0akdsPGpkXgiIbpygb2Sg4g4bh7v6K1cardLV1NwGB9A6u1yICOSDT/MOC//9Ez6EUg==
|
integrity sha512-MGC6sx9jsqHdefhVQ6o0akdsPGpkXgiIbpygb2Sg4g4bh7v6K1cardLV1NwGB9A6u1yICOSDT/MOC//9Ez6EUg==
|
||||||
|
@ -14973,15 +14973,15 @@ react-native-flipper@^0.34.0:
|
||||||
resolved "https://registry.yarnpkg.com/react-native-flipper/-/react-native-flipper-0.34.0.tgz#7df1f38ba5d97a9321125fe0fccbe47d99e6fa1d"
|
resolved "https://registry.yarnpkg.com/react-native-flipper/-/react-native-flipper-0.34.0.tgz#7df1f38ba5d97a9321125fe0fccbe47d99e6fa1d"
|
||||||
integrity sha512-48wgm29HJTOlZ0DibBsvXueEOY0EPIVL0wWKbwRfgrk86+luSEuLW3aZC50oJa95zSFb9qYShTV/6dWqh4Jamg==
|
integrity sha512-48wgm29HJTOlZ0DibBsvXueEOY0EPIVL0wWKbwRfgrk86+luSEuLW3aZC50oJa95zSFb9qYShTV/6dWqh4Jamg==
|
||||||
|
|
||||||
react-native-gesture-handler@^1.10.3:
|
react-native-gesture-handler@2.4.2:
|
||||||
version "1.10.3"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.10.3.tgz#942bbf2963bbf49fa79593600ee9d7b5dab3cfc0"
|
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.4.2.tgz#de93760b0bc251d94e8ae692f9850ec3ed2e4f27"
|
||||||
integrity sha512-cBGMi1IEsIVMgoox4RvMx7V2r6bNKw0uR1Mu1o7NbuHS6BRSVLq0dP34l2ecnPlC+jpWd3le6Yg1nrdCjby2Mw==
|
integrity sha512-K3oMiQV7NOVB5RvNlxkyJxU1Gn6m1cYu53MoFA542FVDSTR491d1eQkWDdqy4lW52rfF7IK7eE1LCi+kTJx7jw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@egjs/hammerjs" "^2.0.17"
|
"@egjs/hammerjs" "^2.0.17"
|
||||||
fbjs "^3.0.0"
|
|
||||||
hoist-non-react-statics "^3.3.0"
|
hoist-non-react-statics "^3.3.0"
|
||||||
invariant "^2.2.4"
|
invariant "^2.2.4"
|
||||||
|
lodash "^4.17.21"
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
|
|
||||||
react-native-image-crop-picker@RocketChat/react-native-image-crop-picker:
|
react-native-image-crop-picker@RocketChat/react-native-image-crop-picker:
|
||||||
|
|
Loading…
Reference in New Issue