Skip to content

Commit d861c92

Browse files
chore(feedback): Improve widget animations
1 parent 7579a06 commit d861c92

File tree

2 files changed

+47
-18
lines changed

2 files changed

+47
-18
lines changed

packages/core/src/js/feedback/FeedbackWidget.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
8888
};
8989

9090
try {
91-
this.setState({ isVisible: false });
91+
if (!onFormSubmitted) {
92+
this.setState({ isVisible: false });
93+
}
9294
captureFeedback(userFeedback, attachments ? { attachments } : undefined);
9395
onSubmitSuccess({ name: trimmedName, email: trimmedEmail, message: trimmedDescription, attachments: undefined });
9496
Alert.alert(text.successMessageText);
@@ -161,8 +163,11 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
161163
const text: FeedbackTextConfiguration = this.props;
162164
const styles: FeedbackWidgetStyles = { ...defaultStyles, ...this.props.styles };
163165
const onCancel = (): void => {
164-
onFormClose();
165-
this.setState({ isVisible: false });
166+
if (onFormClose) {
167+
onFormClose();
168+
} else {
169+
this.setState({ isVisible: false });
170+
}
166171
}
167172

168173
if (!this.state.isVisible) {

packages/core/src/js/feedback/FeedbackWidgetManager.tsx

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { logger } from '@sentry/core';
22
import * as React from 'react';
3-
import { Animated, KeyboardAvoidingView, Modal, PanResponder, Platform } from 'react-native';
3+
import { Animated, Dimensions, KeyboardAvoidingView, Modal, PanResponder, Platform } from 'react-native';
44

55
import { FeedbackWidget } from './FeedbackWidget';
66
import { modalBackground, modalSheetContainer, modalWrapper } from './FeedbackWidget.styles';
@@ -10,6 +10,8 @@ import { isModalSupported } from './utils';
1010

1111
const PULL_DOWN_CLOSE_THREESHOLD = 200;
1212
const PULL_DOWN_ANDROID_ACTIVATION_HEIGHT = 150;
13+
const SLIDE_ANIMATION_DURATION = 150;
14+
const BACKGROUND_ANIMATION_DURATION = 200;
1315

1416
class FeedbackWidgetManager {
1517
private static _isVisible = false;
@@ -53,7 +55,7 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
5355
public state: FeedbackWidgetProviderState = {
5456
isVisible: false,
5557
backgroundOpacity: new Animated.Value(0),
56-
panY: new Animated.Value(0),
58+
panY: new Animated.Value(Dimensions.get('screen').height),
5759
};
5860

5961
private _panResponder = PanResponder.create({
@@ -72,8 +74,8 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
7274
onPanResponderRelease: (_, gestureState) => {
7375
if (gestureState.dy > PULL_DOWN_CLOSE_THREESHOLD) { // Close on swipe below a certain threshold
7476
Animated.timing(this.state.panY, {
75-
toValue: 600,
76-
duration: 200,
77+
toValue: Dimensions.get('screen').height,
78+
duration: SLIDE_ANIMATION_DURATION,
7779
useNativeDriver: true,
7880
}).start(() => {
7981
this._handleClose();
@@ -97,11 +99,20 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
9799
*/
98100
public componentDidUpdate(_prevProps: any, prevState: FeedbackWidgetProviderState): void {
99101
if (!prevState.isVisible && this.state.isVisible) {
100-
Animated.timing(this.state.backgroundOpacity, {
101-
toValue: 1,
102-
duration: 300,
103-
useNativeDriver: true,
104-
}).start();
102+
Animated.parallel([
103+
Animated.timing(this.state.backgroundOpacity, {
104+
toValue: 1,
105+
duration: BACKGROUND_ANIMATION_DURATION,
106+
useNativeDriver: true,
107+
}),
108+
Animated.timing(this.state.panY, {
109+
toValue: 0,
110+
duration: SLIDE_ANIMATION_DURATION,
111+
useNativeDriver: true,
112+
})
113+
]).start(() => {
114+
logger.info('FeedbackWidgetProvider componentDidUpdate');
115+
});
105116
} else if (prevState.isVisible && !this.state.isVisible) {
106117
this.state.backgroundOpacity.setValue(0);
107118
}
@@ -130,7 +141,7 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
130141
{this.props.children}
131142
{isVisible && (
132143
<Animated.View style={[modalWrapper, { backgroundColor }]} >
133-
<Modal visible={isVisible} transparent animationType="slide" onRequestClose={this._handleClose} testID="feedback-form-modal">
144+
<Modal visible={isVisible} transparent animationType="none" onRequestClose={this._handleClose} testID="feedback-form-modal">
134145
<KeyboardAvoidingView
135146
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
136147
style={modalBackground}
@@ -153,15 +164,28 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
153164
}
154165

155166
private _setVisibilityFunction = (visible: boolean): void => {
156-
this.setState({ isVisible: visible });
157-
if (visible) {
158-
this.state.panY.setValue(0);
159-
}
167+
const updateState = () => {
168+
this.setState({ isVisible: visible });
169+
};
170+
171+
Animated.parallel([
172+
Animated.timing(this.state.panY, {
173+
toValue: Dimensions.get('screen').height,
174+
duration: SLIDE_ANIMATION_DURATION,
175+
useNativeDriver: true,
176+
}),
177+
Animated.timing(this.state.backgroundOpacity, {
178+
toValue: 0,
179+
duration: BACKGROUND_ANIMATION_DURATION,
180+
useNativeDriver: true,
181+
})
182+
]).start(() => {
183+
updateState();
184+
});
160185
};
161186

162187
private _handleClose = (): void => {
163188
FeedbackWidgetManager.hide();
164-
this.setState({ isVisible: false });
165189
};
166190
}
167191

0 commit comments

Comments
 (0)