Display the language selection dialog correctly on web (#2719)
* add event to callback * position translation button correctly based on press position * properly place the background * remove worthless commentzio/stable
parent
9ccad0ba6c
commit
52f57b3aec
|
@ -9,15 +9,13 @@ import {
|
||||||
PressableStateCallbackType,
|
PressableStateCallbackType,
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
View,
|
View,
|
||||||
|
NativeSyntheticEvent,
|
||||||
|
NativeTouchEvent,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {choose} from 'lib/functions'
|
import {choose} from 'lib/functions'
|
||||||
|
|
||||||
type Event =
|
|
||||||
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
|
||||||
| GestureResponderEvent
|
|
||||||
|
|
||||||
export type ButtonType =
|
export type ButtonType =
|
||||||
| 'primary'
|
| 'primary'
|
||||||
| 'secondary'
|
| 'secondary'
|
||||||
|
@ -59,7 +57,7 @@ export function Button({
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
labelContainerStyle?: StyleProp<ViewStyle>
|
labelContainerStyle?: StyleProp<ViewStyle>
|
||||||
labelStyle?: StyleProp<TextStyle>
|
labelStyle?: StyleProp<TextStyle>
|
||||||
onPress?: () => void | Promise<void>
|
onPress?: (e: NativeSyntheticEvent<NativeTouchEvent>) => void | Promise<void>
|
||||||
testID?: string
|
testID?: string
|
||||||
accessibilityLabel?: string
|
accessibilityLabel?: string
|
||||||
accessibilityHint?: string
|
accessibilityHint?: string
|
||||||
|
@ -148,11 +146,11 @@ export function Button({
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = React.useState(false)
|
const [isLoading, setIsLoading] = React.useState(false)
|
||||||
const onPressWrapped = React.useCallback(
|
const onPressWrapped = React.useCallback(
|
||||||
async (event: Event) => {
|
async (event: GestureResponderEvent) => {
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
withLoading && setIsLoading(true)
|
withLoading && setIsLoading(true)
|
||||||
await onPress?.()
|
await onPress?.(event)
|
||||||
withLoading && setIsLoading(false)
|
withLoading && setIsLoading(false)
|
||||||
},
|
},
|
||||||
[onPress, withLoading],
|
[onPress, withLoading],
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import React, {PropsWithChildren, useMemo, useRef} from 'react'
|
import React, {PropsWithChildren, useMemo, useRef} from 'react'
|
||||||
import {
|
import {
|
||||||
Dimensions,
|
Dimensions,
|
||||||
|
GestureResponderEvent,
|
||||||
StyleProp,
|
StyleProp,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
TouchableWithoutFeedback,
|
TouchableWithoutFeedback,
|
||||||
|
useWindowDimensions,
|
||||||
View,
|
View,
|
||||||
ViewStyle,
|
ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
|
@ -19,6 +21,7 @@ import {useTheme} from 'lib/ThemeContext'
|
||||||
import {HITSLOP_10} from 'lib/constants'
|
import {HITSLOP_10} from 'lib/constants'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
|
import {isWeb} from 'platform/detection'
|
||||||
|
|
||||||
const ESTIMATED_BTN_HEIGHT = 50
|
const ESTIMATED_BTN_HEIGHT = 50
|
||||||
const ESTIMATED_SEP_HEIGHT = 16
|
const ESTIMATED_SEP_HEIGHT = 16
|
||||||
|
@ -80,21 +83,22 @@ export function DropdownButton({
|
||||||
const ref1 = useRef<TouchableOpacity>(null)
|
const ref1 = useRef<TouchableOpacity>(null)
|
||||||
const ref2 = useRef<View>(null)
|
const ref2 = useRef<View>(null)
|
||||||
|
|
||||||
const onPress = () => {
|
const onPress = (e: GestureResponderEvent) => {
|
||||||
const ref = ref1.current || ref2.current
|
const ref = ref1.current || ref2.current
|
||||||
|
const {height: winHeight} = Dimensions.get('window')
|
||||||
|
const pressY = e.nativeEvent.pageY
|
||||||
ref?.measure(
|
ref?.measure(
|
||||||
(
|
(
|
||||||
_x: number,
|
_x: number,
|
||||||
_y: number,
|
_y: number,
|
||||||
width: number,
|
width: number,
|
||||||
height: number,
|
_height: number,
|
||||||
pageX: number,
|
pageX: number,
|
||||||
pageY: number,
|
pageY: number,
|
||||||
) => {
|
) => {
|
||||||
if (!menuWidth) {
|
if (!menuWidth) {
|
||||||
menuWidth = 200
|
menuWidth = 200
|
||||||
}
|
}
|
||||||
const winHeight = Dimensions.get('window').height
|
|
||||||
let estimatedMenuHeight = 0
|
let estimatedMenuHeight = 0
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (item && isSep(item)) {
|
if (item && isSep(item)) {
|
||||||
|
@ -108,13 +112,16 @@ export function DropdownButton({
|
||||||
const newX = openToRight
|
const newX = openToRight
|
||||||
? pageX + width + rightOffset
|
? pageX + width + rightOffset
|
||||||
: pageX + width - menuWidth
|
: pageX + width - menuWidth
|
||||||
let newY = pageY + height + bottomOffset
|
|
||||||
|
// Add a bit of additional room
|
||||||
|
let newY = pressY + bottomOffset + 20
|
||||||
if (openUpwards || newY + estimatedMenuHeight > winHeight) {
|
if (openUpwards || newY + estimatedMenuHeight > winHeight) {
|
||||||
newY -= estimatedMenuHeight
|
newY -= estimatedMenuHeight
|
||||||
}
|
}
|
||||||
createDropdownMenu(
|
createDropdownMenu(
|
||||||
newX,
|
newX,
|
||||||
newY,
|
newY,
|
||||||
|
pageY,
|
||||||
menuWidth,
|
menuWidth,
|
||||||
items.filter(v => !!v) as DropdownItem[],
|
items.filter(v => !!v) as DropdownItem[],
|
||||||
)
|
)
|
||||||
|
@ -168,6 +175,7 @@ export function DropdownButton({
|
||||||
function createDropdownMenu(
|
function createDropdownMenu(
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
pageY: number,
|
||||||
width: number,
|
width: number,
|
||||||
items: DropdownItem[],
|
items: DropdownItem[],
|
||||||
): RootSiblings {
|
): RootSiblings {
|
||||||
|
@ -185,6 +193,7 @@ function createDropdownMenu(
|
||||||
onOuterPress={onOuterPress}
|
onOuterPress={onOuterPress}
|
||||||
x={x}
|
x={x}
|
||||||
y={y}
|
y={y}
|
||||||
|
pageY={pageY}
|
||||||
width={width}
|
width={width}
|
||||||
items={items}
|
items={items}
|
||||||
onPressItem={onPressItem}
|
onPressItem={onPressItem}
|
||||||
|
@ -198,6 +207,7 @@ type DropDownItemProps = {
|
||||||
onOuterPress: () => void
|
onOuterPress: () => void
|
||||||
x: number
|
x: number
|
||||||
y: number
|
y: number
|
||||||
|
pageY: number
|
||||||
width: number
|
width: number
|
||||||
items: DropdownItem[]
|
items: DropdownItem[]
|
||||||
onPressItem: (index: number) => void
|
onPressItem: (index: number) => void
|
||||||
|
@ -207,6 +217,7 @@ const DropdownItems = ({
|
||||||
onOuterPress,
|
onOuterPress,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
pageY,
|
||||||
width,
|
width,
|
||||||
items,
|
items,
|
||||||
onPressItem,
|
onPressItem,
|
||||||
|
@ -214,6 +225,7 @@ const DropdownItems = ({
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const {height: screenHeight} = useWindowDimensions()
|
||||||
const dropDownBackgroundColor =
|
const dropDownBackgroundColor =
|
||||||
theme.colorScheme === 'dark' ? pal.btn : pal.view
|
theme.colorScheme === 'dark' ? pal.btn : pal.view
|
||||||
const separatorColor =
|
const separatorColor =
|
||||||
|
@ -233,7 +245,21 @@ const DropdownItems = ({
|
||||||
onPress={onOuterPress}
|
onPress={onOuterPress}
|
||||||
accessibilityLabel={_(msg`Toggle dropdown`)}
|
accessibilityLabel={_(msg`Toggle dropdown`)}
|
||||||
accessibilityHint="">
|
accessibilityHint="">
|
||||||
<View style={[styles.bg]} />
|
<View
|
||||||
|
style={[
|
||||||
|
styles.bg,
|
||||||
|
// On web we need to adjust the top and bottom relative to the scroll position
|
||||||
|
isWeb
|
||||||
|
? {
|
||||||
|
top: -pageY,
|
||||||
|
bottom: pageY - screenHeight,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
|
@ -295,10 +321,8 @@ function isBtn(item: DropdownItem): item is DropdownItemButton {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
bg: {
|
bg: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
backgroundColor: '#000',
|
backgroundColor: '#000',
|
||||||
opacity: 0.1,
|
opacity: 0.1,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue