Skip to content

Conversation

bogdandobritoiu
Copy link
Contributor

@bogdandobritoiu bogdandobritoiu commented Aug 21, 2025

Description

Main ticket
Ticket: CP-11496 (Overall native-stack switch)

Also fixes
Ticket: CP-11921 (Bottom tab nav switch to JS from native tabbar)
Ticket: CP-11920 (Toast position)

Summary of changes

  • Improved response time for opening/closing screens
  • Improved response time when closing a screen and immediately tapping another (e.g., open/close portfolio top actions)
  • Enhanced gestures for closing modals on both Android and iOS
  • Adjusted modal + form sheet animations per platform (slightly different per OS, but maintaining consistent UX)
  • Updated navigation headers: all renderLeft and renderRight with SVG icons as children must now use onPressIn / onPressOut
  • Removed @react-navigation/stack patch and module from the codebase
  • Updated screenOptions.tsx; removed useModalScreenOptions.tsx and stackModuleInterpolator.tsx
  • Switched back to auto-focusing via props instead of InteractionManager
  • Refactored screenOptions for all _layouts
  • Added minHeight to ListScreen’s contentContainer to ensure correct snapping with the navigation headerTitle
  • Fixed navigation headerTitle height and animations for show/hide transition
  • (iOS) Added patch for react-native-toast-notifications to display on top of native screens

Remaining Issues

  • (Android) Can't find a way to display PageControl on onboarding on the parent headerTitle

##Screenshots/Videos

iOS
https://github.com/user-attachments/assets/135ab59c-cc04-4aa5-829c-5f2512776076

Android
https://github.com/user-attachments/assets/fce1528a-55e1-478e-8833-40b89cb0f844

Testing

Dev Testing Steps

Please include steps for testing happy path of your feature, and be sure to move this ticket into the "Dev Testing" column

Navigation

  1. Go through onboarding (mnemonic + seedless)
  2. Open/close modals (account / send / swap / etc.) → verify navigation header + gestures
  3. Open list items from portfolio / track → verify animation + back gestures
  4. Stress-test routes for weird behavior:
  • Close a route and immediately open another
  • Ensure no crashes or laggy animations occur
  1. While navigating through screens,
  • verify that the keyboard dismisses correctly
  • verify if all route headers are displaying correctly

Toasts (iOS)

  1. Open swap and try to make a transaction fail so we display the tx failed toast
  2. Verify if toast is on top of all screens

Checklist

Please check all that apply (if applicable)

  • I have performed a self-review of my code
  • I have verified the code works
  • I have included screenshots / videos of android and ios
  • I have added Dev testing steps
  • I have added/updated necessary unit tests
  • I have updated the documentation

Comment on lines +30 to +35
<View
sx={{
height: '100%',
justifyContent: 'center',
alignItems: 'center'
}}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was necessary to add to fill the header height for the navigation button + centering

Comment on lines +3 to +6
createNativeStackNavigator,
NativeStackNavigationEventMap,
NativeStackNavigationOptions
} from '@react-navigation/native-stack'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced /stack with /native-stack

}

// Modals
export const modalScreensOptions: NativeStackNavigationOptions = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Android defaults to formSheet while iOS to pageSheet.
Same applies to the secondary modal on top

Comment on lines +48 to +64
const isPressDisabledRef = useRef(false)

const handlePress = useCallback(() => {
// Prevent multiple presses
if (isPressDisabledRef.current) return

// Disable further presses
isPressDisabledRef.current = true

onPress()

// Re-enable after 300ms
setTimeout(() => {
isPressDisabledRef.current = false
}, 300)
}, [onPress])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prevent multiple presses on token details which would of opened the token details two/three times

<GlobalToast />
<GlobalAlertWithTextInput />
</K2AlpineThemeProvider>
<GestureHandlerRootView>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GestureHandlerRootView is now required

// prevent the header from jumping when navigating
...(Platform.OS === 'ios' && { headerStatusBarHeight: 0 })
contentStyle: {
// iOS will display empty content without this
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS needs contentHeight 100% for formSheet otherwise the screen is white

@bogdandobritoiu bogdandobritoiu marked this pull request as ready for review August 22, 2025 21:10
Comment on lines -272 to -292
const animatedContainerStyle = useAnimatedStyle(() => {
let bottomOffset = keyboard.isVisible ? keyboard.height - insets.bottom : 0

if (hasTabBar) {
if (keyboard.isVisible) {
bottomOffset =
keyboard.height - (Platform.OS === 'ios' ? 0 : tabBarHeight)
} else {
bottomOffset = Platform.OS === 'ios' ? tabBarHeight : 0
}
}

return {
// TODO: Couldn't make Android work with keyboard avoidance, so we need to add a bottom offset
// iOS works with automaticallyAdjustKeyboardInsets but we do keep the same thing here for consistency
paddingBottom: withTiming(bottomOffset, {
...ANIMATED.TIMING_CONFIG,
duration: 50
})
}
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had issues with Keyboard avoiding list contents after switching from /stack which handled this differently.
I simplified code since this was now broken

Comment on lines +20 to +22
<TouchableOpacity
// onPress doesn't work for Android when using svgs (only on production)
onPressOut={onPress}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SVG content for headerLeft/headerRight doesn't work when using onPress for Android on production, so onPressOut works as expected and has better UX

Comment on lines +42 to +44
export const secondaryModalScreensOptions: NativeStackNavigationOptions = {
...modalScreensOptions,
sheetAllowedDetents: [Platform.OS === 'android' ? 0.92 : 0.99]
Copy link
Contributor Author

@bogdandobritoiu bogdandobritoiu Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use this only for approval or select token/network modal

Comment on lines +75 to +81
const trimmedUrl = trimTrailingSlash(historyPayload.url)
const historyId = createHash(trimmedUrl)
const history = {
id: historyId,
lastVisited,
...historyPayload
...historyPayload,
url: trimmedUrl
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was breaking with new redux bumped version from main

Comment on lines +579 to +586
<View
style={{
position: 'absolute',
bottom: 0,
left: 0,
right: 0
}}
onLayout={handleSegmentedControlLayout}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all SegmentedControls have a wrapper with absolute positioning because tabbar is positioned absolute

Comment on lines +31 to +37
useEffect(() => {
const navigationOptions: NativeStackNavigationOptions = {
headerTitle: renderPageControl
}
navigation.getParent()?.setOptions(navigationOptions)
}, [navigation, renderPageControl])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOs works, couldn't make PageControl show up on Android though. Confirmed with design, not a big deal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant