Skip to content

Commit

Permalink
feat: receive sheet navigator, closes LEA-1699
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Nov 5, 2024
1 parent 9885823 commit 2c573e9
Show file tree
Hide file tree
Showing 18 changed files with 246 additions and 78 deletions.
17 changes: 6 additions & 11 deletions apps/mobile/src/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useRef } from 'react';
import { StatusBar } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Provider as ReduxProvider } from 'react-redux';

import { LeatherQueryProvider } from '@/common/leather-query-provider';
import SheetNavigatorWrapper from '@/common/sheet-navigator/sheet-navigator-wrapper';
import { SplashScreenGuard } from '@/components/splash-screen-guard/splash-screen-guard';
import { ToastWrapper } from '@/components/toast/toast-context';
import { ReceiveSheet } from '@/features/receive/receive-sheet';
import { SendSheet } from '@/features/send/send-sheet';
import { SendSheetProvider } from '@/features/send/send-sheet-context';
import { initiateI18n } from '@/locales';
import { queryClient } from '@/queries/query';
import { persistor, store } from '@/store';
Expand All @@ -21,12 +21,7 @@ import { Slot } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { PersistGate } from 'redux-persist/integration/react';

import {
Box,
ThemeProvider as LeatherThemeProvider,
SheetProvider,
SheetRef,
} from '@leather.io/ui/native';
import { Box, ThemeProvider as LeatherThemeProvider, SheetProvider } from '@leather.io/ui/native';

void SplashScreen.preventAutoHideAsync();

Expand All @@ -39,7 +34,6 @@ export const unstable_settings = { initialRouteName: '/' };
initiateI18n();

Check warning on line 34 in apps/mobile/src/app/_layout.tsx

View workflow job for this annotation

GitHub Actions / lint-eslint

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator

Check warning on line 34 in apps/mobile/src/app/_layout.tsx

View workflow job for this annotation

GitHub Actions / lint-eslint

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator

Check warning on line 34 in apps/mobile/src/app/_layout.tsx

View workflow job for this annotation

GitHub Actions / lint-eslint

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator

export default function RootLayout() {
const sendSheetRef = useRef<SheetRef>(null);
return (
<ReduxProvider store={store}>
<PersistGate loading={null} persistor={persistor}>
Expand All @@ -51,12 +45,13 @@ export default function RootLayout() {
<SplashScreenGuard>
<GestureHandlerRootView style={{ flex: 1 }}>
<SheetProvider>
<SendSheetProvider value={{ sendSheetRef }}>
<SheetNavigatorWrapper>
<ToastWrapper>
<AppRouter />
<SendSheet />
<ReceiveSheet />
</ToastWrapper>
</SendSheetProvider>
</SheetNavigatorWrapper>
</SheetProvider>
</GestureHandlerRootView>
</SplashScreenGuard>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useWindowDimensions } from 'react-native';

import { HasChildren } from '@/utils/types';
import { NavigationContainer } from '@react-navigation/native';

import { Box } from '@leather.io/ui/native';

export function SheetNavigationContainer({ children }: HasChildren) {
const { height } = useWindowDimensions();
return (
<Box flex={1} height={height}>
<NavigationContainer independent>{children}</NavigationContainer>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createContext, useContext } from 'react';

import { SheetRef } from '@leather.io/ui/native';

export interface SheetNavigatorContext {
sendSheetRef: React.RefObject<SheetRef>;
receiveSheetRef: React.RefObject<SheetRef>;
}

const sheetNavigatorContext = createContext<SheetNavigatorContext | null>(null);

export const SheetNavigatorProvider = sheetNavigatorContext.Provider;

export function useSheetNavigatorContext() {
const context = useContext(sheetNavigatorContext);
if (!context)
throw new Error('`useSheetNavigatorContext` must be used within a `SheetNavigatorProvider`');
return context;
}
18 changes: 18 additions & 0 deletions apps/mobile/src/common/sheet-navigator/sheet-navigator-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useRef } from 'react';

import { HasChildren } from '@/utils/types';

import { SheetRef } from '@leather.io/ui/native';

import { SheetNavigatorProvider } from './sheet-navigator-provider';

export default function SheetNavigatorWrapper({ children }: HasChildren) {
const sendSheetRef = useRef<SheetRef>(null);
const receiveSheetRef = useRef<SheetRef>(null);

return (
<SheetNavigatorProvider value={{ sendSheetRef, receiveSheetRef }}>
{children}
</SheetNavigatorProvider>
);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ReactNode, RefObject, createContext, forwardRef, useContext, useRef } from 'react';
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';

import { useSheetNavigatorContext } from '@/common/sheet-navigator/sheet-navigator-provider';
import { ActionBar, ActionBarMethods } from '@/components/action-bar/action-bar';
import { useSendSheetContext } from '@/features/send/send-sheet-context';
import { AppRoutes } from '@/routes';
import { TestId } from '@/shared/test-id';
import { useWallets } from '@/store/wallets/wallets.read';
Expand Down Expand Up @@ -147,10 +147,10 @@ function ActionBarButton({ onPress, icon, label, testID }: ActionBarButtonProps)
}

export const ActionBarContainer = forwardRef<ActionBarMethods>((_, ref) => {
const { sendSheetRef, receiveSheetRef } = useSheetNavigatorContext();
const router = useRouter();
const wallets = useWallets();
const addWalletSheetRef = useRef<SheetRef>(null);
const { sendSheetRef } = useSendSheetContext();

const actionBar = isEmptyArray(wallets.list) ? (
<ActionBar
Expand Down Expand Up @@ -182,7 +182,7 @@ export const ActionBarContainer = forwardRef<ActionBarMethods>((_, ref) => {
}
center={
<ActionBarButton
onPress={() => router.navigate(AppRoutes.Receive)}
onPress={() => receiveSheetRef.current?.present()}
icon={<InboxIcon />}
label={t({
id: 'action_bar.receive_label',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReactNode } from 'react';

import { HeaderTitleWithSubtitle } from './components/header-title-with-subtitle';
import { HeaderLayout } from './header.layout';
import { HeaderTitleWithSubtitle } from '../headers/components/header-title-with-subtitle';
import { HeaderLayout } from '../headers/header.layout';

interface FullHeightSheetHeaderProps {
title: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { useTheme } from '@shopify/restyle';

import { Box, Theme } from '@leather.io/ui/native';

interface SendSheetLayoutProps extends HasChildren {
interface FullHeightSheetLayoutProps extends HasChildren {
header: React.ReactNode;
}
export function SendSheetLayout({ children, header }: SendSheetLayoutProps) {
export function FullHeightSheetLayout({ children, header }: FullHeightSheetLayoutProps) {
const { bottom } = useSafeAreaInsets();
const theme = useTheme<Theme>();

Expand Down
35 changes: 35 additions & 0 deletions apps/mobile/src/features/receive/receive-sheet-navigator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Account } from '@/store/accounts/accounts';
import { ParamListBase } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useTheme } from '@shopify/restyle';

import { Theme } from '@leather.io/ui/native';

import { SelectAccount } from './receive-sheets/select-account';
import { SelectAsset } from './receive-sheets/select-asset';

export interface ReceiveSheetNavigatorParamList extends ParamListBase {
'receive-select-account': undefined;
'receive-select-asset': { account: Account };
}

const Stack = createStackNavigator<ReceiveSheetNavigatorParamList>();

export function ReceiveSheetNavigator() {
const theme = useTheme<Theme>();
return (
<Stack.Navigator
initialRouteName="receive-select-account"
screenOptions={{
headerShown: false,
cardStyle: {
backgroundColor: theme.colors['ink.background-primary'],
overflow: 'visible',
},
}}
>
<Stack.Screen name="receive-select-account" component={SelectAccount} />
<Stack.Screen name="receive-select-asset" component={SelectAsset} />
</Stack.Navigator>
);
}
16 changes: 16 additions & 0 deletions apps/mobile/src/features/receive/receive-sheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { SheetNavigationContainer } from '@/common/sheet-navigator/sheet-navigation-container';
import { useSheetNavigatorContext } from '@/common/sheet-navigator/sheet-navigator-provider';
import { FullHeightSheet } from '@/components/full-height-sheet/full-height-sheet';

import { ReceiveSheetNavigator } from './receive-sheet-navigator';

export function ReceiveSheet() {
const { receiveSheetRef } = useSheetNavigatorContext();
return (
<FullHeightSheet sheetRef={receiveSheetRef}>
<SheetNavigationContainer>
<ReceiveSheetNavigator />
</SheetNavigationContainer>
</FullHeightSheet>
);
}
35 changes: 35 additions & 0 deletions apps/mobile/src/features/receive/receive-sheets/select-account.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { FullHeightSheetHeader } from '@/components/full-height-sheet/full-height-sheet-header';
import { FullHeightSheetLayout } from '@/components/full-height-sheet/full-height-sheet.layout';
import { NetworkBadge } from '@/components/network-badge';
import { AccountList } from '@/features/account-list/account-list';
import { Account } from '@/store/accounts/accounts';
import { useAccounts } from '@/store/accounts/accounts.read';
import { t } from '@lingui/macro';
import { NavigationProp, useNavigation } from '@react-navigation/native';

import { ReceiveSheetNavigatorParamList } from '../receive-sheet-navigator';

export function SelectAccount() {
const navigation = useNavigation<NavigationProp<ReceiveSheetNavigatorParamList>>();
const accounts = useAccounts();

function onSelectAccount(account: Account) {
navigation.navigate('receive-select-asset', { account });
}

return (
<FullHeightSheetLayout
header={
<FullHeightSheetHeader
title={t({
id: 'select_account.header_title',
message: 'Select account',
})}
rightElement={<NetworkBadge />}
/>
}
>
<AccountList accounts={accounts.list} onPress={onSelectAccount} showWalletInfo />
</FullHeightSheetLayout>
);
}
39 changes: 39 additions & 0 deletions apps/mobile/src/features/receive/receive-sheets/select-asset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { FullHeightSheetHeader } from '@/components/full-height-sheet/full-height-sheet-header';
import { FullHeightSheetLayout } from '@/components/full-height-sheet/full-height-sheet.layout';
import { NetworkBadge } from '@/components/network-badge';
import { t } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { RouteProp, useRoute } from '@react-navigation/native';

import { Text } from '@leather.io/ui/native';

import { ReceiveSheetNavigatorParamList } from '../receive-sheet-navigator';

type SelectAssetScreenRouteProp = RouteProp<ReceiveSheetNavigatorParamList, 'receive-select-asset'>;

export function SelectAsset() {
const { i18n } = useLingui();
const route = useRoute<SelectAssetScreenRouteProp>();
const subtitle = route.params?.account?.name;

return (
<FullHeightSheetLayout
header={
<FullHeightSheetHeader
title={t({
id: 'select_asset.header_title',
message: 'Select asset',
})}
subtitle={i18n._({
id: 'select_asset.header_subtitle',
message: '{subtitle}',
values: { subtitle },
})}
rightElement={<NetworkBadge />}
/>
}
>
<Text>{t`Token list`}</Text>
</FullHeightSheetLayout>
);
}
17 changes: 0 additions & 17 deletions apps/mobile/src/features/send/send-sheet-context.tsx

This file was deleted.

30 changes: 14 additions & 16 deletions apps/mobile/src/features/send/send-sheet-navigator.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Account } from '@/store/accounts/accounts';
import { NavigationContainer, ParamListBase } from '@react-navigation/native';
import { ParamListBase } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useTheme } from '@shopify/restyle';

Expand All @@ -18,20 +18,18 @@ const Stack = createStackNavigator<SendSheetNavigatorParamList>();
export function SendSheetNavigator() {
const theme = useTheme<Theme>();
return (
<NavigationContainer independent>
<Stack.Navigator
initialRouteName="send-select-account"
screenOptions={{
headerShown: false,
cardStyle: {
backgroundColor: theme.colors['ink.background-primary'],
overflow: 'visible',
},
}}
>
<Stack.Screen name="send-select-account" component={SelectAccount} />
<Stack.Screen name="send-select-asset" component={SelectAsset} />
</Stack.Navigator>
</NavigationContainer>
<Stack.Navigator
initialRouteName="send-select-account"
screenOptions={{
headerShown: false,
cardStyle: {
backgroundColor: theme.colors['ink.background-primary'],
overflow: 'visible',
},
}}
>
<Stack.Screen name="send-select-account" component={SelectAccount} />
<Stack.Screen name="send-select-asset" component={SelectAsset} />
</Stack.Navigator>
);
}
16 changes: 6 additions & 10 deletions apps/mobile/src/features/send/send-sheet.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import { useWindowDimensions } from 'react-native';

import { FullHeightSheet } from '@/components/sheets/full-height-sheet';
import { useSendSheetContext } from '@/features/send/send-sheet-context';

import { Box } from '@leather.io/ui/native';
import { SheetNavigationContainer } from '@/common/sheet-navigator/sheet-navigation-container';
import { useSheetNavigatorContext } from '@/common/sheet-navigator/sheet-navigator-provider';
import { FullHeightSheet } from '@/components/full-height-sheet/full-height-sheet';

import { SendSheetNavigator } from './send-sheet-navigator';

export function SendSheet() {
const { height } = useWindowDimensions();
const { sendSheetRef } = useSendSheetContext();
const { sendSheetRef } = useSheetNavigatorContext();
return (
<FullHeightSheet sheetRef={sendSheetRef}>
<Box flex={1} height={height}>
<SheetNavigationContainer>
<SendSheetNavigator />
</Box>
</SheetNavigationContainer>
</FullHeightSheet>
);
}
Loading

0 comments on commit 2c573e9

Please sign in to comment.