Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -83,39 +83,42 @@ const IncomingCallHeader = memo(
/>
</A11y.Index>
<View style={styles.row}>
<A11y.Index index={3} style={{ flex: 1 }}>
<A11y.Index index={3}>
<Touch
hitSlop={BUTTON_HIT_SLOP}
onPress={() => {
setAudio(!audio);
hideNotification();
}}
accessibilityLabel={i18n.t('A11y_incoming_call_dismiss')}
style={styles.closeButton}>
style={styles.closeButton}
rectButtonStyle={styles.closeButtonContainer}>
<CustomIcon name='close' size={20} />
</Touch>
</A11y.Index>
<A11y.Index index={4} style={{ flex: 1 }}>
<A11y.Index index={4} style={styles.buttonWrapper}>
<Touch
hitSlop={BUTTON_HIT_SLOP}
onPress={() => {
setAudio(!audio);
hideNotification();
dispatch(cancelCall({ callId }));
}}
style={styles.cancelButton}>
style={styles.cancelButton}
rectButtonStyle={styles.buttonContainer}>
<Text style={styles.buttonText}>{i18n.t('decline')}</Text>
</Touch>
</A11y.Index>
<A11y.Index index={5} style={{ flex: 1 }}>
<A11y.Index index={5} style={styles.buttonWrapper}>
<Touch
hitSlop={BUTTON_HIT_SLOP}
onPress={() => {
setAudio(!audio);
hideNotification();
dispatch(acceptCall({ callId }));
}}
style={styles.acceptButton}>
style={styles.acceptButton}
rectButtonStyle={styles.buttonContainer}>
<Text style={styles.buttonText}>{i18n.t('accept')}</Text>
</Touch>
</A11y.Index>
Expand Down
35 changes: 22 additions & 13 deletions app/containers/InAppNotification/IncomingCallNotification/style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { PixelRatio, StyleSheet } from 'react-native';
import { useTheme } from '../../../theme';
import sharedStyles from '../../../views/Styles';

const BUTTON_HEIGHT = 36;

export const useStyle = () => {
const { colors } = useTheme();
return StyleSheet.create({
Expand All @@ -25,33 +27,40 @@ export const useStyle = () => {
flexDirection: 'row',
marginTop: 12
},
// Touch only forwards backgroundColor, borderRadius and margins to the RectButton, so sizing
// goes through rectButtonStyle - on style it lands on the inner View and the button collapses
closeButton: {
backgroundColor: colors.buttonBackgroundSecondaryDefault,
marginRight: 8,
borderRadius: 4
},
closeButtonContainer: {
width: BUTTON_HEIGHT,
height: BUTTON_HEIGHT,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 4,
width: 36,
height: 36
justifyContent: 'center'
},
cancelButton: {
borderRadius: 4,
backgroundColor: colors.buttonBackgroundDangerDefault,
marginRight: 8,
flex: 2,
marginRight: 8
},
acceptButton: {
borderRadius: 4,
backgroundColor: colors.buttonBackgroundSuccessDefault
},
// decline and accept share the remaining width evenly, minHeight so the label can grow
buttonWrapper: {
flex: 1
},
buttonContainer: {
minHeight: BUTTON_HEIGHT,
alignItems: 'center',
justifyContent: 'center'
},
buttonText: {
...sharedStyles.textMedium,
color: 'white'
},
acceptButton: {
borderRadius: 4,
backgroundColor: colors.buttonBackgroundSuccessDefault,
flex: 2,
alignItems: 'center',
justifyContent: 'center'
}
});
};
3 changes: 2 additions & 1 deletion app/containers/InAppNotification/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
notification
},
duration: notification.customTime || (process.env.RUNNING_E2E_TESTS ? 5000 : 3000), // default 3s,
hideOnPress: notification.hideOnPress ?? true,
// our components handle their own presses; the library's press wrapper swallows taps on them
hideOnPress: notification.hideOnPress ?? false,
swipeEnabled: notification.swipeEnabled ?? true
});
}
Expand All @@ -71,7 +72,7 @@
return () => {
EventEmitter.removeListener(INAPP_NOTIFICATION_EMITTER, listener);
};
}, [subscribedRoom, appState]);

Check warning on line 75 in app/containers/InAppNotification/index.tsx

View workflow job for this annotation

GitHub Actions / format

React Hook useEffect has a missing dependency: 'show'. Either include it or remove the dependency array

Check warning on line 75 in app/containers/InAppNotification/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint and Test / run-eslint-and-test

React Hook useEffect has a missing dependency: 'show'. Either include it or remove the dependency array

return <NotifierRoot />;
});
Expand Down
49 changes: 39 additions & 10 deletions patches/react-native-notifier+1.6.1.patch
Original file line number Diff line number Diff line change
@@ -1,49 +1,78 @@
diff --git a/node_modules/react-native-notifier/src/Notifier.tsx b/node_modules/react-native-notifier/src/Notifier.tsx
index 56c5819..4f31e78 100644
--- a/node_modules/react-native-notifier/src/Notifier.tsx
+++ b/node_modules/react-native-notifier/src/Notifier.tsx
@@ -44,6 +44,7 @@ export class NotifierRoot extends React.PureComponent<ShowNotificationParams, St
@@ -44,6 +44,8 @@
Component: NotificationComponent,
swipeEnabled: DEFAULT_SWIPE_ENABLED,
componentProps: {},
+ visible: false,
+ pressable: false,
};
this.isShown = false;
this.isHiding = false;
@@ -146,6 +147,7 @@ export class NotifierRoot extends React.PureComponent<ShowNotificationParams, St
@@ -146,6 +148,8 @@
Component: Component ?? NotificationComponent,
swipeEnabled: swipeEnabled ?? DEFAULT_SWIPE_ENABLED,
componentProps: componentProps,
+ visible: true,
+ pressable: !!restParams.onPress || restParams.hideOnPress !== false,
});

this.showParams = restParams;
@@ -188,6 +190,7 @@ export class NotifierRoot extends React.PureComponent<ShowNotificationParams, St
@@ -188,6 +192,7 @@
}

private onHidden() {
+ this.setState({ visible: false })
this.showParams?.onHidden?.();
this.isShown = false;
this.isHiding = false;
@@ -259,7 +262,7 @@ export class NotifierRoot extends React.PureComponent<ShowNotificationParams, St
@@ -241,7 +246,7 @@
}

render() {
- const { title, description, swipeEnabled, Component, componentProps } = this.state;
+ const { title, description, swipeEnabled, Component, componentProps, pressable } = this.state;

return (
<PanGestureHandler
@@ -257,11 +262,23 @@
},
]}
>
<TouchableWithoutFeedback onPress={this.onPress}>
<View onLayout={this.onLayout}>
- <TouchableWithoutFeedback onPress={this.onPress}>
- <View onLayout={this.onLayout}>
- <Component title={title} description={description} {...componentProps} />
+ {/* The RN Touchable wrapper is only mounted when the notification actually needs a
+ wrapper-level press. An RN Pressability ancestor claims the RN responder as soon as the
+ touch stream contains any movement, which cancels the native touch on any
+ react-native-gesture-handler button rendered inside the notification: the button's
+ Android pressed flag is cleared, so NativeViewGestureHandler.canActivate() is false at
+ ACTION_UP and onPress never fires. See Rocket.Chat.ReactNative#115357. */}
+ {pressable ? (
+ <TouchableWithoutFeedback onPress={this.onPress}>
+ <View onLayout={this.onLayout}>
+ {this.state.visible? <Component title={title} description={description} {...componentProps} /> : null}
+ </View>
+ </TouchableWithoutFeedback>
+ ) : (
+ <View onLayout={this.onLayout}>
+ {this.state.visible? <Component title={title} description={description} {...componentProps} /> : null}
</View>
</TouchableWithoutFeedback>
- </TouchableWithoutFeedback>
+ )}
</Animated.View>
</PanGestureHandler>
);
diff --git a/node_modules/react-native-notifier/src/types.ts b/node_modules/react-native-notifier/src/types.ts
index 229e19c..e16a943 100644
--- a/node_modules/react-native-notifier/src/types.ts
+++ b/node_modules/react-native-notifier/src/types.ts
@@ -95,6 +95,7 @@ export interface StateInterface {
@@ -95,6 +95,8 @@
swipeEnabled: boolean;
Component: ElementType;
componentProps: Record<string, any>;
+ visible: boolean;
+ pressable: boolean;
}

export interface NotifierInterface {
Loading