1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-11 18:24:43 +02:00

Mobile: Dismiss dialogs on background tap (#10557)

This commit is contained in:
Henry Heino 2024-06-10 14:31:06 -07:00 committed by GitHub
parent 97d15bb26a
commit 80aeff6ecd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 55 additions and 31 deletions

View File

@ -29,8 +29,8 @@ const useStyles = (themeId: number, containerStyle: ViewStyle, size: DialogSize)
return useMemo(() => {
const theme = themeStyle(themeId);
const maxWidth = size === DialogSize.Large ? Infinity : 500;
const maxHeight = size === DialogSize.Large ? Infinity : 700;
const maxWidth = size === DialogSize.Large ? windowSize.width : 500;
const maxHeight = size === DialogSize.Large ? windowSize.height : 700;
return StyleSheet.create({
webView: {
@ -45,29 +45,27 @@ const useStyles = (themeId: number, containerStyle: ViewStyle, size: DialogSize)
flexDirection: 'row',
justifyContent: 'flex-end',
},
dialog: {
backgroundColor: theme.backgroundColor,
borderRadius: 12,
padding: 10,
// Use Math.min with width and height -- the maxWidth and maxHeight style
// properties don't seem to limit the size for this.
height: Math.min(maxHeight, windowSize.height * 0.9),
width: Math.min(maxWidth, windowSize.width * 0.97),
dialogContainer: {
maxHeight,
maxWidth,
width: '100%',
height: '100%',
flexShrink: 1,
// Center
marginLeft: 'auto',
marginRight: 'auto',
paddingLeft: 6,
paddingRight: 6,
...containerStyle,
},
dialogContainer: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
flexGrow: 1,
dialogSurface: {
borderRadius: 12,
backgroundColor: theme.backgroundColor,
padding: 10,
width: '100%',
height: '100%',
},
});
}, [themeId, windowSize.width, windowSize.height, containerStyle, size]);
@ -96,7 +94,7 @@ const DismissibleDialog: React.FC<Props> = props => {
backgroundColor='rgba(0, 0, 0, 0.1)'
transparent={true}
>
<Surface style={styles.dialog} elevation={1}>
<Surface style={styles.dialogSurface} elevation={1}>
{closeButton}
{props.children}
</Surface>

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import { useMemo } from 'react';
import { Modal, ModalProps, StyleSheet, View, ViewStyle, useWindowDimensions } from 'react-native';
import { RefObject, useCallback, useMemo, useRef } from 'react';
import { GestureResponderEvent, Modal, ModalProps, StyleSheet, View, ViewStyle, useWindowDimensions } from 'react-native';
import { hasNotch } from 'react-native-device-info';
interface ModalElementProps extends ModalProps {
@ -13,21 +13,39 @@ const useStyles = (backgroundColor?: string) => {
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
const isLandscape = windowWidth > windowHeight;
return useMemo(() => {
const backgroundPadding: ViewStyle = isLandscape ? {
paddingRight: hasNotch() ? 60 : 0,
paddingLeft: hasNotch() ? 60 : 0,
paddingTop: 15,
paddingBottom: 15,
} : {
paddingTop: hasNotch() ? 65 : 15,
paddingBottom: hasNotch() ? 35 : 15,
};
return StyleSheet.create({
contentWrapper: isLandscape ? {
marginRight: hasNotch() ? 60 : 0,
marginLeft: hasNotch() ? 60 : 0,
marginTop: 15,
marginBottom: 15,
} : {
marginTop: hasNotch() ? 65 : 15,
marginBottom: hasNotch() ? 35 : 15,
modalBackground: {
...backgroundPadding,
backgroundColor,
flexGrow: 1,
},
modalBackground: { backgroundColor, flexGrow: 1 },
});
}, [isLandscape, backgroundColor]);
};
const useBackgroundTouchListeners = (onRequestClose: (event: GestureResponderEvent)=> void, backdropRef: RefObject<View>) => {
const onShouldBackgroundCaptureTouch = useCallback((event: GestureResponderEvent) => {
return event.target === backdropRef.current && event.nativeEvent.touches.length === 1;
}, [backdropRef]);
const onBackgroundTouchFinished = useCallback((event: GestureResponderEvent) => {
if (event.target === backdropRef.current) {
onRequestClose?.(event);
}
}, [onRequestClose, backdropRef]);
return { onShouldBackgroundCaptureTouch, onBackgroundTouchFinished };
};
const ModalElement: React.FC<ModalElementProps> = ({
children,
containerStyle,
@ -39,18 +57,26 @@ const ModalElement: React.FC<ModalElementProps> = ({
// contentWrapper adds padding. To allow styling the region outside of the modal
// (e.g. to add a background), the content is wrapped twice.
const content = (
<View style={[styles.contentWrapper, containerStyle]}>
<View style={containerStyle}>
{children}
</View>
);
const backgroundRef = useRef<View>();
const { onShouldBackgroundCaptureTouch, onBackgroundTouchFinished } = useBackgroundTouchListeners(modalProps.onRequestClose, backgroundRef);
// supportedOrientations: On iOS, this allows the dialog to be shown in non-portrait orientations.
return (
<Modal
supportedOrientations={['portrait', 'portrait-upside-down', 'landscape', 'landscape-left', 'landscape-right']}
{...modalProps}
>
<View style={styles.modalBackground}>{content}</View>
<View
ref={backgroundRef}
style={styles.modalBackground}
onStartShouldSetResponder={onShouldBackgroundCaptureTouch}
onResponderRelease={onBackgroundTouchFinished}
>{content}</View>
</Modal>
);
};