diff --git a/src/__tests__/scenes/__snapshots__/CreateWalletSelectCryptoScene.test.tsx.snap b/src/__tests__/scenes/__snapshots__/CreateWalletSelectCryptoScene.test.tsx.snap index 5bdfd6eeecf..754a6244f7a 100644 --- a/src/__tests__/scenes/__snapshots__/CreateWalletSelectCryptoScene.test.tsx.snap +++ b/src/__tests__/scenes/__snapshots__/CreateWalletSelectCryptoScene.test.tsx.snap @@ -2293,6 +2293,7 @@ exports[`CreateWalletSelectCrypto should render with loading props 1`] = ` ] } nativeID="10" + onLayout={[Function]} style={ [ { diff --git a/src/__tests__/scenes/__snapshots__/FioConnectWalletConfirmScene.test.tsx.snap b/src/__tests__/scenes/__snapshots__/FioConnectWalletConfirmScene.test.tsx.snap index 730f9f50dbd..4d716a7ff42 100644 --- a/src/__tests__/scenes/__snapshots__/FioConnectWalletConfirmScene.test.tsx.snap +++ b/src/__tests__/scenes/__snapshots__/FioConnectWalletConfirmScene.test.tsx.snap @@ -357,15 +357,10 @@ exports[`FioConnectWalletConfirm should render with loading props 1`] = ` diff --git a/src/__tests__/scenes/__snapshots__/SwapConfirmationScene.test.tsx.snap b/src/__tests__/scenes/__snapshots__/SwapConfirmationScene.test.tsx.snap index ab3a3f33d1a..6dbf122dcf9 100644 --- a/src/__tests__/scenes/__snapshots__/SwapConfirmationScene.test.tsx.snap +++ b/src/__tests__/scenes/__snapshots__/SwapConfirmationScene.test.tsx.snap @@ -273,97 +273,92 @@ exports[`SwapConfirmationScene should render with loading props 1`] = ` - - - Exchange - - - + > + Exchange + + + + diff --git a/src/__tests__/scenes/__snapshots__/TransactionDetailsScene.test.tsx.snap b/src/__tests__/scenes/__snapshots__/TransactionDetailsScene.test.tsx.snap index 04ce071b11b..5b860764e76 100644 --- a/src/__tests__/scenes/__snapshots__/TransactionDetailsScene.test.tsx.snap +++ b/src/__tests__/scenes/__snapshots__/TransactionDetailsScene.test.tsx.snap @@ -228,15 +228,10 @@ exports[`TransactionDetailsScene should render 1`] = ` @@ -3121,15 +3116,10 @@ exports[`TransactionDetailsScene should render with negative nativeAmount and fi diff --git a/src/components/common/SceneWrapper.tsx b/src/components/common/SceneWrapper.tsx index b8b41b68695..a484d35d953 100644 --- a/src/components/common/SceneWrapper.tsx +++ b/src/components/common/SceneWrapper.tsx @@ -171,6 +171,9 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement { const navigation = useNavigation() const isIos = Platform.OS === 'ios' + // Track dock height for content padding when dockProps is used + const [dockHeight, setDockHeight] = useState(0) + // We need to track this state in the JS thread because insets are not shared values const [isKeyboardOpen, setIsKeyboardOpen] = useState(false) useKeyboardHandler({ @@ -240,6 +243,12 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement { // Ignore inset bottom when keyboard is open because it is rendered behind it const maybeInsetBottom = !isKeyboardOpen || !avoidKeyboard ? safeAreaInsets.bottom : 0 + // Include dock height in bottom inset when dock is visible (not keyboard-only or keyboard is open) + const keyboardVisibleOnlyDock = dockProps?.keyboardVisibleOnly ?? true + const maybeDockHeight = + dockProps != null && (!keyboardVisibleOnlyDock || isKeyboardOpen) + ? dockHeight + : 0 const insets: EdgeInsets = useMemo( () => ({ top: hasHeader ? headerBarHeight : safeAreaInsets.top, @@ -248,13 +257,15 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement { maybeInsetBottom + maybeNotificationHeight + maybeTabBarHeight + - footerHeight, + footerHeight + + maybeDockHeight, left: safeAreaInsets.left }), [ footerHeight, hasHeader, headerBarHeight, + maybeDockHeight, maybeInsetBottom, maybeNotificationHeight, maybeTabBarHeight, @@ -328,7 +339,12 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement { }, [children, sceneWrapperInfo]) // Build Dock View element - const keyboardVisibleOnlyDoc = dockProps?.keyboardVisibleOnly ?? true + const handleDockLayout = React.useCallback( + (event: { nativeEvent: { layout: { height: number } } }) => { + setDockHeight(event.nativeEvent.layout.height) + }, + [] + ) const dockBaseStyle = useMemo( () => ({ position: 'absolute' as const, @@ -366,9 +382,10 @@ function SceneWrapperComponent(props: SceneWrapperProps): React.ReactElement { return { bottom } }) const shouldShowDock = - dockProps != null && (!keyboardVisibleOnlyDoc || isKeyboardVisibleDock) + dockProps != null && (!keyboardVisibleOnlyDock || isKeyboardVisibleDock) const dockElement = !shouldShowDock ? null : ( = (props: Props) => { - const { children, headerTitle, headerTitleChildren, ...sceneContainerProps } = - props + const { children, headerTitle, headerTitleChildren, undoInsetStyle } = props + + const theme = useTheme() + const styles = getStyles(theme) + + const contentInsets = React.useMemo( + () => ({ + ...undoInsetStyle, + flex: 1, + marginTop: 0, + // Built-in padding if we're not using undoInsetStyle + paddingHorizontal: + undoInsetStyle == null ? theme.rem(DEFAULT_MARGIN_REM) : 0, + paddingBottom: undoInsetStyle == null ? theme.rem(DEFAULT_MARGIN_REM) : 0 + }), + [theme, undoInsetStyle] + ) return ( - + <> {headerTitle != null ? ( - - {headerTitleChildren} - + + + {headerTitle} + {headerTitleChildren} + + + ) : null} - {children} - + {children} + ) } -interface SceneContainerViewProps { - expand?: boolean - undoTop?: boolean - undoRight?: boolean - undoBottom?: boolean - undoLeft?: boolean - undoInsetStyle?: UndoInsetStyle -} -const SceneContainerView = styled(View)( - theme => - ({ expand, undoTop, undoRight, undoBottom, undoLeft, undoInsetStyle }) => ({ - flex: expand === true ? 1 : undefined, - paddingTop: theme.rem(0.5), - paddingRight: theme.rem(0.5), - paddingBottom: theme.rem(0.5), - paddingLeft: theme.rem(0.5), - marginTop: undoTop === true ? undoInsetStyle?.marginTop : undefined, - marginRight: undoRight === true ? undoInsetStyle?.marginRight : undefined, - marginBottom: - undoBottom === true ? undoInsetStyle?.marginBottom : undefined, - marginLeft: undoLeft === true ? undoInsetStyle?.marginLeft : undefined - }) -) +const getStyles = cacheStyles((theme: Theme) => ({ + headerContainer: { + justifyContent: 'center', + overflow: 'visible', + paddingLeft: theme.rem(DEFAULT_MARGIN_REM) + }, + title: { + fontSize: theme.rem(1.2), + fontFamily: theme.fontFaceMedium + }, + titleContainer: { + alignItems: 'center', + flexDirection: 'row', + justifyContent: 'space-between', + marginHorizontal: theme.rem(DEFAULT_MARGIN_REM), + marginBottom: theme.rem(DEFAULT_MARGIN_REM) + } +})) diff --git a/src/components/scenes/DuressPinScene.tsx b/src/components/scenes/DuressPinScene.tsx index 7280bc45fb1..c41ba4d79a3 100644 --- a/src/components/scenes/DuressPinScene.tsx +++ b/src/components/scenes/DuressPinScene.tsx @@ -19,7 +19,7 @@ import { DigitInput, MAX_PIN_LENGTH } from './inputs/DigitInput' interface Props extends EdgeAppSceneProps<'duressPin'> {} -export const DuressPinScene = (props: Props) => { +export const DuressPinScene: React.FC = (props: Props) => { const { navigation } = props const theme = useTheme() const styles = getStyles(theme) @@ -29,7 +29,7 @@ export const DuressPinScene = (props: Props) => { const [pin, setPin] = React.useState('') const isValidPin = pin.length === MAX_PIN_LENGTH - const handleComplete = () => { + const handleComplete = useHandler(() => { if (!isValidPin) return account .checkPin(pin) @@ -47,10 +47,10 @@ export const DuressPinScene = (props: Props) => { showToast(lstrings.duress_mode_set_pin_success) navigation.navigate('duressModeSetting') }) - .catch(err => { + .catch((err: unknown) => { showError(err) }) - } + }) const handleChangePin = useHandler((newPin: string) => { // Change pin only when input are numbers @@ -66,7 +66,7 @@ export const DuressPinScene = (props: Props) => { return ( - + = props => { return ( - + {error != null ? ( diff --git a/src/components/scenes/Staking/StakeOptionsScene.tsx b/src/components/scenes/Staking/StakeOptionsScene.tsx index 0f4e8558ca2..5c12a7b371d 100644 --- a/src/components/scenes/Staking/StakeOptionsScene.tsx +++ b/src/components/scenes/Staking/StakeOptionsScene.tsx @@ -30,7 +30,6 @@ import { SceneContainer } from '../../layout/SceneContainer' import { Space } from '../../layout/Space' import { useTheme } from '../../services/ThemeContext' import { EdgeText } from '../../themed/EdgeText' -import { SceneHeaderUi4 } from '../../themed/SceneHeaderUi4' interface Props extends EdgeAppSceneProps<'stakeOptions'> { wallet: EdgeCurrencyWallet @@ -41,7 +40,7 @@ export interface StakeOptionsParams { walletId: string } -const StakeOptionsSceneComponent = (props: Props) => { +const StakeOptionsSceneComponent = (props: Props): React.JSX.Element => { const { navigation, route, wallet } = props const { tokenId } = route.params const [stakePlugins = []] = useAsyncValue( @@ -73,7 +72,7 @@ const StakeOptionsSceneComponent = (props: Props) => { // Handlers // - const handleStakeOptionPress = (stakePolicy: StakePolicy) => { + const handleStakeOptionPress = (stakePolicy: StakePolicy): void => { const { stakePolicyId } = stakePolicy const stakePlugin = getPluginFromPolicyId(stakePlugins, stakePolicyId, { pluginId @@ -90,7 +89,11 @@ const StakeOptionsSceneComponent = (props: Props) => { // Renders // - const renderOptions = ({ item: stakePolicy }: { item: StakePolicy }) => { + const renderOptions = ({ + item: stakePolicy + }: { + item: StakePolicy + }): React.JSX.Element => { const primaryText = getPolicyAssetName(stakePolicy, 'stakeAssets') const secondaryText = getPolicyTitleName(stakePolicy, countryCode) const key = [primaryText, secondaryText].join() @@ -143,27 +146,21 @@ const StakeOptionsSceneComponent = (props: Props) => { overrideDots={theme.backgroundDots.assetOverrideDots} > {({ undoInsetStyle, insetStyle }) => ( - + - {/* TODO: Decide if our design language accepts scene headers within - the scroll area of a scene. If so, we must make the SceneContainer - component implement FlatList components. This is a one-off - until then. */} - - - {lstrings.stake_select_options} - - + + {lstrings.stake_select_options} + } keyExtractor={(stakePolicy: StakePolicy) => stakePolicy.stakePolicyId diff --git a/src/components/scenes/SwapCreateScene.tsx b/src/components/scenes/SwapCreateScene.tsx index 13130513eeb..f42ec8d90b1 100644 --- a/src/components/scenes/SwapCreateScene.tsx +++ b/src/components/scenes/SwapCreateScene.tsx @@ -535,7 +535,7 @@ export const SwapCreateScene: React.FC = props => { }} > {({ isKeyboardOpen }) => ( - + {fromWallet == null ? (