diff --git a/src/components/DappBrowser/control-panel/ControlPanel.tsx b/src/components/DappBrowser/control-panel/ControlPanel.tsx index 99c24dd0597..94977e35f14 100644 --- a/src/components/DappBrowser/control-panel/ControlPanel.tsx +++ b/src/components/DappBrowser/control-panel/ControlPanel.tsx @@ -311,7 +311,7 @@ export const ControlPanel = () => { ); }; -const TapToDismiss = memo(function TapToDismiss() { +export const TapToDismiss = memo(function TapToDismiss() { const { goBack } = useNavigation(); return ( diff --git a/src/components/Discover/TrendingTokens.tsx b/src/components/Discover/TrendingTokens.tsx index e76e6b339d5..0c3e0fba658 100644 --- a/src/components/Discover/TrendingTokens.tsx +++ b/src/components/Discover/TrendingTokens.tsx @@ -7,7 +7,6 @@ import { analyticsV2 } from '@/analytics'; import { useBackendNetworksStore } from '@/state/backendNetworks/backendNetworks'; import { ChainId } from '@/state/backendNetworks/types'; import { ChainImage } from '@/components/coin-icon/ChainImage'; -import { NetworkSelector } from '@/components/NetworkSwitcher'; import Skeleton, { FakeAvatar, FakeText } from '@/components/skeleton/Skeleton'; import { SortDirection, TrendingCategory, TrendingSort } from '@/graphql/__generated__/arc'; import { formatCurrency, formatNumber } from '@/helpers/strings'; @@ -21,7 +20,7 @@ import { sortFilters, timeFilters, useTrendingTokensStore } from '@/state/trendi import { colors } from '@/styles'; import { darkModeThemeColors } from '@/styles/colors'; import { useTheme } from '@/theme'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import React, { Dimensions, FlatList, View } from 'react-native'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; @@ -489,7 +488,6 @@ function NoResults() { } function NetworkFilter() { - const [isOpen, setOpen] = useState(false); const selected = useSharedValue(undefined); const { chainId, setChainId } = useTrendingTokensStore(state => ({ @@ -513,12 +511,14 @@ function NetworkFilter() { return ; }, [chainId]); - return ( - <> - setOpen(true)} /> - {isOpen && setOpen(false)} />} - - ); + const navigateToNetworkSelector = useCallback(() => { + Navigation.handleAction(Routes.NETWORK_SELECTOR, { + selected, + setSelected, + }); + }, [selected, setSelected]); + + return ; } function TimeFilter() { diff --git a/src/components/NetworkSwitcher.tsx b/src/components/NetworkSwitcher.tsx index a5853c3a00d..d61ac55213d 100644 --- a/src/components/NetworkSwitcher.tsx +++ b/src/components/NetworkSwitcher.tsx @@ -2,21 +2,21 @@ import { getChainColorWorklet } from '@/__swaps__/utils/swaps'; import { useBackendNetworksStore } from '@/state/backendNetworks/backendNetworks'; import { ChainId } from '@/state/backendNetworks/types'; -import { AbsolutePortal } from '@/components/AbsolutePortal'; import { AnimatedBlurView } from '@/components/AnimatedComponents/AnimatedBlurView'; import { ButtonPressAnimation } from '@/components/animations'; import { SPRING_CONFIGS } from '@/components/animations/animationConfigs'; import { AnimatedChainImage, ChainImage } from '@/components/coin-icon/ChainImage'; -import { AnimatedText, DesignSystemProvider, globalColors, Separator, Text, useBackgroundColor, useColorMode } from '@/design-system'; +import { AnimatedText, Box, DesignSystemProvider, globalColors, Separator, Text, useBackgroundColor, useColorMode } from '@/design-system'; import { useForegroundColor } from '@/design-system/color/useForegroundColor'; import * as i18n from '@/languages'; import { useTheme } from '@/theme'; -import { DEVICE_WIDTH } from '@/utils/deviceUtils'; +import deviceUtils, { DEVICE_WIDTH } from '@/utils/deviceUtils'; import MaskedView from '@react-native-masked-view/masked-view'; import chroma from 'chroma-js'; import { PropsWithChildren, ReactElement, useEffect } from 'react'; -import React, { Pressable, View } from 'react-native'; -import { Gesture, GestureDetector, State, TapGesture } from 'react-native-gesture-handler'; +import React, { Pressable, StyleSheet, View } from 'react-native'; +import { RouteProp, useRoute } from '@react-navigation/native'; +import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; import Animated, { FadeIn, @@ -44,6 +44,11 @@ import { networkSwitcherStore, shouldShowCustomizeNetworksBanner, } from '@/state/networkSwitcher/networkSwitcher'; +import { RootStackParamList } from '@/navigation/types'; +import { IS_IOS } from '@/env'; +import { safeAreaInsetValues } from '@/utils'; +import { noop } from 'lodash'; +import { TapToDismiss } from './DappBrowser/control-panel/ControlPanel'; const t = i18n.l.network_switcher; @@ -708,80 +713,64 @@ function NetworksGrid({ ); } -function SheetBackdrop({ onPress }: { onPress: VoidFunction }) { - const tapGesture = Gesture.Tap().onEnd(onPress); - return ( - - - - ); -} - -function Sheet({ children, header, onClose }: PropsWithChildren<{ header: ReactElement; onClose: VoidFunction }>) { +function Sheet({ children, editing, onClose }: PropsWithChildren<{ editing: SharedValue; onClose: VoidFunction }>) { const { isDarkMode } = useTheme(); const surfacePrimary = useBackgroundColor('surfacePrimary'); const backgroundColor = isDarkMode ? '#191A1C' : surfacePrimary; const separatorSecondary = useForegroundColor('separatorSecondary'); - const translationY = useSharedValue(0); - - const swipeToClose = Gesture.Pan() - .onChange(event => { - if (event.translationY < 0) return; - translationY.value = event.translationY; - }) - .onFinalize(() => { - if (translationY.value > 120) runOnJS(onClose)(); - else translationY.value = withSpring(0); - }); - - const sheetStyle = useAnimatedStyle(() => ({ transform: [{ translateY: translationY.value }] })); + // make sure the onClose function is called when the sheet unmounts + useEffect(() => { + return () => onClose?.(); + }, [onClose]); return ( - - - - - - {header} - {children} - - - + <> + +
+ {children} + + + ); } -export function NetworkSelector({ - onClose, - selected, - setSelected, -}: { - onClose: VoidFunction; - selected: SharedValue; - setSelected: (chainId: ChainId | undefined) => void; -}) { +export function NetworkSelector() { + const { + params: { onClose = noop, selected, setSelected }, + } = useRoute>(); + const editing = useSharedValue(false); return ( - } onClose={onClose}> + ); } + +const sx = StyleSheet.create({ + sheet: { + flex: 1, + width: deviceUtils.dimensions.width - 16, + bottom: Math.max(safeAreaInsetValues.bottom + 5, IS_IOS ? 8 : 30), + pointerEvents: 'box-none', + position: 'absolute', + zIndex: 30000, + left: 8, + right: 8, + paddingHorizontal: 16, + borderRadius: 42, + borderWidth: 1.33, + }, +}); diff --git a/src/featuresToUnlock/tokenGatedUtils.ts b/src/featuresToUnlock/tokenGatedUtils.ts index 4b399e013b7..52085c56724 100644 --- a/src/featuresToUnlock/tokenGatedUtils.ts +++ b/src/featuresToUnlock/tokenGatedUtils.ts @@ -79,4 +79,4 @@ export const checkIfWalletsOwnNft1155 = async ( } catch (e) { return false; } -}; \ No newline at end of file +}; diff --git a/src/navigation/Routes.android.tsx b/src/navigation/Routes.android.tsx index d246a004f6a..05b09059948 100644 --- a/src/navigation/Routes.android.tsx +++ b/src/navigation/Routes.android.tsx @@ -90,6 +90,7 @@ import { ControlPanel } from '@/components/DappBrowser/control-panel/ControlPane import { ClaimRewardsPanel } from '@/screens/points/claim-flow/ClaimRewardsPanel'; import { ClaimClaimablePanel } from '@/screens/claimables/ClaimPanel'; import { RootStackParamList } from './types'; +import { NetworkSelector } from '@/components/NetworkSwitcher'; const Stack = createStackNavigator(); const OuterStack = createStackNavigator(); @@ -242,6 +243,7 @@ function BSNavigator() { + diff --git a/src/navigation/Routes.ios.tsx b/src/navigation/Routes.ios.tsx index e65e309538a..c07ef6294b5 100644 --- a/src/navigation/Routes.ios.tsx +++ b/src/navigation/Routes.ios.tsx @@ -70,6 +70,7 @@ import { swapConfig, checkIdentifierSheetConfig, recieveModalSheetConfig, + networkSelectorConfig, } from './config'; import { addCashSheet, emojiPreset, emojiPresetWallet, overlayExpandedPreset, sheetPreset } from './effects'; import { InitialRouteContext } from './initialRoute'; @@ -102,6 +103,7 @@ import { ControlPanel } from '@/components/DappBrowser/control-panel/ControlPane import { ClaimRewardsPanel } from '@/screens/points/claim-flow/ClaimRewardsPanel'; import { ClaimClaimablePanel } from '@/screens/claimables/ClaimPanel'; import { RootStackParamList } from './types'; +import { NetworkSelector } from '@/components/NetworkSwitcher'; const Stack = createStackNavigator(); const NativeStack = createNativeStackNavigator(); @@ -273,6 +275,7 @@ function NativeStackNavigator() { + diff --git a/src/navigation/config.tsx b/src/navigation/config.tsx index 5428d27e37b..38b7a0032fe 100644 --- a/src/navigation/config.tsx +++ b/src/navigation/config.tsx @@ -248,6 +248,20 @@ export const consoleSheetConfig = { }), }; +export const networkSelectorConfig = { + options: ({ route: { params = {} } }) => ({ + ...buildCoolModalConfig({ + ...params, + backgroundColor: '#000000B2', + backgroundOpacity: 0.7, + cornerRadius: 0, + springDamping: 1, + topOffset: 0, + transitionDuration: 0.3, + }), + }), +}; + export const panelConfig = { options: ({ route: { params = {} } }) => ({ ...buildCoolModalConfig({ diff --git a/src/navigation/routesNames.ts b/src/navigation/routesNames.ts index 96cc67fb146..ff4372906e3 100644 --- a/src/navigation/routesNames.ts +++ b/src/navigation/routesNames.ts @@ -100,6 +100,7 @@ const Routes = { SETTINGS_SECTION_NOTIFICATIONS: 'NotificationsSection', SETTINGS_SECTION_PRIVACY: 'PrivacySection', DAPP_BROWSER_CONTROL_PANEL: 'DappBrowserControlPanel', + NETWORK_SELECTOR: 'NetworkSelector', CLAIM_REWARDS_PANEL: 'ClaimRewardsPanel', } as const; diff --git a/src/navigation/types.ts b/src/navigation/types.ts index 409bc90740e..c1877d015da 100644 --- a/src/navigation/types.ts +++ b/src/navigation/types.ts @@ -11,6 +11,8 @@ import { WalletconnectApprovalSheetRouteParams, WalletconnectResultType } from ' import { WalletConnectApprovalSheetType } from '@/helpers/walletConnectApprovalSheetTypes'; import { RainbowPosition } from '@/resources/defi/types'; import { Address } from 'viem'; +import { SharedValue } from 'react-native-reanimated'; +import { ChainId } from '@/state/backendNetworks/types'; export type PartialNavigatorConfigOptions = Pick['Screen']>[0]>, 'options'>; @@ -105,4 +107,9 @@ export type RootStackParamList = { [Routes.POSITION_SHEET]: { position: RainbowPosition; }; + [Routes.NETWORK_SELECTOR]: { + onClose?: VoidFunction; + selected: SharedValue; + setSelected: (chainId: ChainId | undefined) => void; + }; }; diff --git a/src/state/assets/userAssets.ts b/src/state/assets/userAssets.ts index e161ec1dc99..d667880acdb 100644 --- a/src/state/assets/userAssets.ts +++ b/src/state/assets/userAssets.ts @@ -10,52 +10,7 @@ import { swapsStore } from '@/state/swaps/swapsStore'; import { ChainId } from '@/state/backendNetworks/types'; import { useBackendNetworksStore } from '@/state/backendNetworks/backendNetworks'; import { useSelector } from 'react-redux'; -<<<<<<< HEAD import { getUniqueId } from '@/utils/ethereumUtils'; -======= - -const SEARCH_CACHE_MAX_ENTRIES = 50; - -const escapeRegExp = (string: string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -const getSearchQueryKey = ({ filter, searchQuery }: { filter: UserAssetFilter; searchQuery: string }) => `${filter}${searchQuery}`; - -const getDefaultCacheKeys = (): Set => { - const queryKeysToPreserve = new Set(); - queryKeysToPreserve.add('all'); - - for (const chainId of useBackendNetworksStore.getState().getSupportedChainIds()) { - queryKeysToPreserve.add(`${chainId}`); - } - return queryKeysToPreserve; -}; - -const CACHE_ITEMS_TO_PRESERVE = getDefaultCacheKeys(); - -export interface UserAssetsState { - chainBalances: Map; - currentAbortController: AbortController; - filter: UserAssetFilter; - idsByChain: Map; - inputSearchQuery: string; - searchCache: Map; - userAssets: Map; - getBalanceSortedChainList: () => ChainId[]; - getChainsWithBalance: () => ChainId[]; - getFilteredUserAssetIds: () => UniqueId[]; - getHighestValueNativeAsset: () => ParsedSearchAsset | null; - getUserAsset: (uniqueId: UniqueId) => ParsedSearchAsset | null; - getUserAssets: () => ParsedSearchAsset[]; - selectUserAssetIds: (selector: (asset: ParsedSearchAsset) => boolean, filter?: UserAssetFilter) => Generator; - selectUserAssets: (selector: (asset: ParsedSearchAsset) => boolean) => Generator<[UniqueId, ParsedSearchAsset], void, unknown>; - setSearchCache: (queryKey: string, filteredIds: UniqueId[]) => void; - setSearchQuery: (query: string) => void; - setUserAssets: (userAssets: Map | ParsedSearchAsset[]) => void; - - hiddenAssets: Set; - getHiddenAssetsIds: () => UniqueId[]; - setHiddenAssets: (uniqueIds: UniqueId[]) => void; -} ->>>>>>> e67803ca7 (convert network accessors to functions (#6219)) type UserAssetsStateToPersist = Omit< Partial,