Skip to content

Commit 5780488

Browse files
committed
Merge branch 'feedback-ui' into kw-use-widget-insted-form
# Conflicts: # packages/core/src/js/feedback/FeedbackWidgetManager.tsx
2 parents ca33345 + 874b2a2 commit 5780488

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

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

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

55
import { FeedbackWidget } from './FeedbackWidget';
66
import { modalBackground, modalSheetContainer, modalWrapper } from './FeedbackWidget.styles';
77
import type { FeedbackWidgetStyles } from './FeedbackWidget.types';
88
import { getFeedbackOptions } from './integration';
99
import { isModalSupported } from './utils';
1010

11+
const PULL_DOWN_CLOSE_THREESHOLD = 200;
12+
const PULL_DOWN_ANDROID_ACTIVATION_HEIGHT = 150;
13+
1114
class FeedbackWidgetManager {
1215
private static _isVisible = false;
1316
private static _setVisibility: (visible: boolean) => void;
@@ -43,14 +46,47 @@ interface FeedbackWidgetProviderProps {
4346
interface FeedbackWidgetProviderState {
4447
isVisible: boolean;
4548
backgroundOpacity: Animated.Value;
49+
panY: Animated.Value;
4650
}
4751

4852
class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps> {
4953
public state: FeedbackWidgetProviderState = {
5054
isVisible: false,
5155
backgroundOpacity: new Animated.Value(0),
56+
panY: new Animated.Value(0),
5257
};
5358

59+
private _panResponder = PanResponder.create({
60+
onStartShouldSetPanResponder: (evt, _gestureState) => {
61+
// On Android allow pulling down only from the top to avoid breaking native gestures
62+
return Platform.OS !== 'android' || evt.nativeEvent.pageY < PULL_DOWN_ANDROID_ACTIVATION_HEIGHT;
63+
},
64+
onMoveShouldSetPanResponder: (evt, _gestureState) => {
65+
return Platform.OS !== 'android' || evt.nativeEvent.pageY < PULL_DOWN_ANDROID_ACTIVATION_HEIGHT;
66+
},
67+
onPanResponderMove: (_, gestureState) => {
68+
if (gestureState.dy > 0) {
69+
this.state.panY.setValue(gestureState.dy);
70+
}
71+
},
72+
onPanResponderRelease: (_, gestureState) => {
73+
if (gestureState.dy > PULL_DOWN_CLOSE_THREESHOLD) { // Close on swipe below a certain threshold
74+
Animated.timing(this.state.panY, {
75+
toValue: 600,
76+
duration: 200,
77+
useNativeDriver: true,
78+
}).start(() => {
79+
this._handleClose();
80+
});
81+
} else { // Animate it back to the original position
82+
Animated.spring(this.state.panY, {
83+
toValue: 0,
84+
useNativeDriver: true,
85+
}).start();
86+
}
87+
},
88+
});
89+
5490
public constructor(props: FeedbackWidgetProviderProps) {
5591
super(props);
5692
FeedbackWidgetManager.initialize(this._setVisibilityFunction);
@@ -99,12 +135,15 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
99135
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
100136
style={modalBackground}
101137
>
102-
<View style={modalSheetContainer}>
138+
<Animated.View
139+
style={[modalSheetContainer, { transform: [{ translateY: this.state.panY }] }]}
140+
{...this._panResponder.panHandlers}
141+
>
103142
<FeedbackWidget {...getFeedbackOptions()}
104143
onFormClose={this._handleClose}
105144
onFormSubmitted={this._handleClose}
106145
/>
107-
</View>
146+
</Animated.View>
108147
</KeyboardAvoidingView>
109148
</Modal>
110149
</Animated.View>
@@ -115,6 +154,9 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
115154

116155
private _setVisibilityFunction = (visible: boolean): void => {
117156
this.setState({ isVisible: visible });
157+
if (visible) {
158+
this.state.panY.setValue(0);
159+
}
118160
};
119161

120162
private _handleClose = (): void => {

0 commit comments

Comments
 (0)