Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] User review prompt #3457

Merged
merged 18 commits into from Dec 4, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/components/Nav/App/index.js
Expand Up @@ -3,6 +3,7 @@ import { NavigationContainer, CommonActions } from '@react-navigation/native';
import { Animated } from 'react-native';
import { createStackNavigator } from '@react-navigation/stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
import AsyncStorage from '@react-native-community/async-storage';
import Login from '../../Views/Login';
import QRScanner from '../../Views/QRScanner';
import Onboarding from '../../Views/Onboarding';
Expand All @@ -29,9 +30,8 @@ import Logger from '../../../util/Logger';
import { trackErrorAsAnalytics } from '../../../util/analyticsV2';
import { routingInstrumentation } from '../../../util/setupSentry';
import Analytics from '../../../core/Analytics';
import AsyncStorage from '@react-native-community/async-storage';
import ReviewManager from '../../../core/ReviewManager';
import { connect } from 'react-redux';

import { EXISTING_USER, CURRENT_APP_VERSION, LAST_APP_VERSION } from '../../../constants/storage';
import { getVersion } from 'react-native-device-info';

Expand Down Expand Up @@ -262,6 +262,7 @@ const App = ({ userLoggedIn }) => {
ref={navigator}
onReady={() => {
routingInstrumentation.registerNavigationContainer(navigator);
ReviewManager.navigationRef = navigator;
}}
>
<Stack.Navigator route={route} initialRouteName={route}>
Expand Down
16 changes: 0 additions & 16 deletions app/components/Nav/Main/MainNavigator.js
Expand Up @@ -5,7 +5,6 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Browser from '../../Views/Browser';
import AddBookmark from '../../Views/AddBookmark';
import SimpleWebview from '../../Views/SimpleWebview';
import Approval from '../../Views/Approval';
import Settings from '../../Views/Settings';
import GeneralSettings from '../../Views/Settings/GeneralSettings';
import AdvancedSettings from '../../Views/Settings/AdvancedSettings';
Expand Down Expand Up @@ -39,7 +38,6 @@ import ImportPrivateKey from '../../Views/ImportPrivateKey';
import ImportPrivateKeySuccess from '../../Views/ImportPrivateKeySuccess';
import PaymentRequest from '../../UI/PaymentRequest';
import PaymentRequestSuccess from '../../UI/PaymentRequestSuccess';
import Approve from '../../Views/ApproveView/Approve';
import Amount from '../../Views/SendFlow/Amount';
import Confirm from '../../Views/SendFlow/Confirm';
import ContactForm from '../../Views/Settings/Contacts/ContactForm';
Expand Down Expand Up @@ -214,18 +212,6 @@ const SendFlowView = () => (
</Stack.Navigator>
);

const ApprovalView = () => (
<Stack.Navigator>
<Stack.Screen name="Approval" component={Approval} options={Approval.navigationOptions} />
</Stack.Navigator>
);

const ApproveView = () => (
<Stack.Navigator>
<Stack.Screen name="Approve" component={Approve} options={Approve.navigationOptions} />
</Stack.Navigator>
);

const AddBookmarkView = () => (
<Stack.Navigator>
<Stack.Screen name="AddBookmark" component={AddBookmark} options={AddBookmark.navigationOptions} />
Expand Down Expand Up @@ -336,8 +322,6 @@ const MainNavigator = () => (
<Stack.Screen name="ImportPrivateKeyView" component={ImportPrivateKeyView} />
<Stack.Screen name="SendView" component={SendView} />
<Stack.Screen name="SendFlowView" component={SendFlowView} />
<Stack.Screen name="ApprovalView" component={ApprovalView} />
<Stack.Screen name="ApproveView" component={ApproveView} />
<Stack.Screen name="AddBookmarkView" component={AddBookmarkView} />
<Stack.Screen name="OfflineModeView" component={OfflineModeView} />
<Stack.Screen name="QRScanner" component={QrScanner} />
Expand Down
Expand Up @@ -2,6 +2,6 @@

exports[`Main should render correctly 1`] = `
<ForwardRef(NavigationContainer)>
<Connect(Main) />
<MainFlow />
</ForwardRef(NavigationContainer)>
`;
18 changes: 17 additions & 1 deletion app/components/Nav/Main/index.js
Expand Up @@ -71,7 +71,10 @@ import { getTokenList } from '../../../reducers/tokens';
import { toLowerCaseEquals } from '../../../util/general';
import { ethers } from 'ethers';
import abi from 'human-standard-token-abi';
import { createStackNavigator } from '@react-navigation/stack';
import ReviewModal from '../../UI/ReviewModal';

const Stack = createStackNavigator();
const hstInterface = new ethers.utils.Interface(abi);

const styles = StyleSheet.create({
Expand Down Expand Up @@ -808,4 +811,17 @@ const mapDispatchToProps = (dispatch) => ({
removeNotVisibleNotifications: () => dispatch(removeNotVisibleNotifications()),
});

export default connect(mapStateToProps, mapDispatchToProps)(Main);
const ConnectedMain = connect(mapStateToProps, mapDispatchToProps)(Main);

const MainFlow = () => (
<Stack.Navigator
initialRouteName={'Main'}
mode={'modal'}
screenOptions={{ headerShown: false, cardStyle: { backgroundColor: 'transparent' } }}
>
<Stack.Screen name={'Main'} component={ConnectedMain} />
<Stack.Screen name={'ReviewModal'} component={ReviewModal} options={{ animationEnabled: false }} />
</Stack.Navigator>
);

export default MainFlow;
2 changes: 1 addition & 1 deletion app/components/UI/CollectibleModal/index.js
Expand Up @@ -84,7 +84,7 @@ const CollectibleModal = (props) => {
const modalRef = useRef(null);

return (
<ReusableModal ref={modalRef} onDismiss={() => navigation.navigate('WalletView')} style={styles.bottomModal}>
<ReusableModal ref={modalRef} style={styles.bottomModal}>
<>
<View style={[styles.collectibleMediaWrapper, { zIndex: mediaZIndex, elevation: mediaZIndex }]}>
<CollectibleMedia
Expand Down
81 changes: 38 additions & 43 deletions app/components/UI/ReusableModal/index.tsx
@@ -1,5 +1,7 @@
/* eslint-disable */
import React, { useEffect, ReactNode, forwardRef, useImperativeHandle, useMemo, useCallback, useRef } from 'react';
import { View, TouchableOpacity, StyleSheet, ViewStyle, Dimensions, StyleProp } from 'react-native';
import { useNavigation } from '@react-navigation/core';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { PanGestureHandler, State } from 'react-native-gesture-handler';
import Animated, {
Expand All @@ -13,29 +15,30 @@ import Animated, {
Value,
interpolate,
useCode,
set
set,
} from 'react-native-reanimated';
import { onGestureEvent, withSpring, clamp, timing, spring } from 'react-native-redash';
import { colors } from '../../../styles/common';
import { onGestureEvent, withSpring, clamp, timing } from 'react-native-redash';
import styles from './styles';
const screenHeight = Dimensions.get('window').height;

type DismissModal = () => void;

type Actions = {
export interface ReusableModalRef {
dismissModal: (callback?: DismissModal) => void;
};
}

type Props = {
ref?: React.Ref<Actions>;
interface Props {
ref?: React.Ref<ReusableModalRef>;
style?: StyleProp<ViewStyle>;
children?: ReactNode;
onDismiss?: DismissModal;
};
}

const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
const ReusableModal = forwardRef<ReusableModalRef, Props>((props, ref) => {
const { style, children, onDismiss } = props;
const topOffset = 0;
const bottomOffset = screenHeight;
const navigation = useNavigation();
const safeAreaInsets = useSafeAreaInsets();
const trigger = useRef<DismissModal>();

Expand All @@ -46,12 +49,16 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
restSpeedThreshold: 5,
restDisplacementThreshold: 5,
stiffness: 800,
mass: 6
mass: 6,
};

// Animation is finished, process end state
const triggerDismissed = useCallback(() => {
// Remove modal from stack
navigation.goBack();
// Declaratively
onDismiss && onDismiss();
// Imperatively
trigger.current && trigger.current();
}, [onDismiss]);

Expand All @@ -66,7 +73,7 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
() =>
clamp(
withSpring({
onSnap: val => {
onSnap: (val) => {
const offset = val[0];
if (offset == bottomOffset) {
// TODO: Use optional chaining once prettier is fixed
Expand All @@ -78,7 +85,7 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
offset,
value: translationY,
snapPoints: [topOffset, bottomOffset],
config: animationConfig
config: animationConfig,
}),
topOffset,
bottomOffset
Expand All @@ -101,26 +108,26 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
overlayBackground: {
opacity: interpolate(translateY, {
inputRange: [topOffset, bottomOffset],
outputRange: [1, 0]
}) as any
outputRange: [1, 0],
}) as any,
},
overlayBackgroundTouchable: {
...StyleSheet.absoluteFillObject,
transform: [
{
translateY: interpolate(translateY, {
inputRange: [0, 1],
outputRange: [0, bottomOffset]
}) as any
}
]
outputRange: [0, bottomOffset],
}) as any,
},
],
},
modal: {
transform: [{ translateY } as any],
// TODO: This could be used to handle universal safe area bottom padding
// paddingBottom: safeAreaInsets.bottom
flex: 1
}
flex: 1,
},
};
}, [topOffset, bottomOffset, translateY, safeAreaInsets]);

Expand All @@ -132,15 +139,16 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
cond(eq(triggerShowModal, new Value(1)), [
set(
offset,
spring({
config: animationConfig,
timing({
clock,
from: offset,
to: topOffset
easing: Easing.inOut(Easing.ease),
duration: 250,
to: topOffset,
})
),
// Reset value that toggles animating in overlay
cond(not(clockRunning(clock)), block([set(triggerShowModal, 0)]))
cond(not(clockRunning(clock)), block([set(triggerShowModal, 0)])),
]),
// Animate OUT overlay
cond(eq(triggerDismissModal, new Value(1)), [
Expand All @@ -149,17 +157,17 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
timing({
clock,
from: offset,
easing: Easing.ease,
easing: Easing.inOut(Easing.ease),
duration: 200,
to: bottomOffset
to: bottomOffset,
})
),
// Dismiss overlay after animating out
cond(
not(clockRunning(clock)),
block([call([], () => triggerDismissed()), set(triggerDismissModal, 0)])
)
])
),
]),
]),
[]
);
Expand All @@ -171,10 +179,10 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {

// Expose actions for external components
useImperativeHandle(ref, () => ({
dismissModal: callback => {
dismissModal: (callback) => {
trigger.current = callback;
dismissOverlay();
}
},
}));

const renderOverlay = useCallback(() => {
Expand Down Expand Up @@ -202,17 +210,4 @@ const ReusableModal = forwardRef<Actions, Props>((props, ref) => {
);
});

const styles = StyleSheet.create({
container: {
flex: 1
},
overlayBackground: {
backgroundColor: colors.overlay,
...StyleSheet.absoluteFillObject
},
fill: {
flex: 1
}
});

export default ReusableModal;
15 changes: 15 additions & 0 deletions app/components/UI/ReusableModal/styles.ts
@@ -0,0 +1,15 @@
import { StyleSheet } from 'react-native';
import { colors } from '../../../styles/common';

export default StyleSheet.create({
Cal-L marked this conversation as resolved.
Show resolved Hide resolved
container: {
flex: 1,
},
overlayBackground: {
backgroundColor: colors.overlay,
...StyleSheet.absoluteFillObject,
},
fill: {
flex: 1,
},
});