diff --git a/machines/bleShare/request/requestMachine.ts b/machines/bleShare/request/requestMachine.ts index ee66e005b3..6cff685a31 100644 --- a/machines/bleShare/request/requestMachine.ts +++ b/machines/bleShare/request/requestMachine.ts @@ -405,7 +405,7 @@ export const requestMachine = }, on: { DISMISS: { - target: 'navigatingToHistory', + target: 'displayingIncomingVC', }, }, }, @@ -431,11 +431,27 @@ export const requestMachine = displayingIncomingVC: { on: { GO_TO_RECEIVED_VC_TAB: { - target: 'navigatingToHistory', + target: 'navigatingToReceivedCards', + }, + }, + }, + navigatingToReceivedCards: { + on: { + DISMISS: { + target: 'navigatingToHome', + }, + }, + }, + navigatingToHome: { + invoke: { + src: 'disconnect', + }, + on: { + DISCONNECT: { + target: '#request.inactive', }, }, }, - savingFailed: { initial: 'idle', entry: ['setReceiveLogTypeDiscarded', 'logReceived'], diff --git a/machines/bleShare/request/requestMachine.typegen.ts b/machines/bleShare/request/requestMachine.typegen.ts index 79fcc938fa..c480767d5c 100644 --- a/machines/bleShare/request/requestMachine.typegen.ts +++ b/machines/bleShare/request/requestMachine.typegen.ts @@ -30,7 +30,8 @@ export interface Typegen0 { checkStorageAvailability: 'done.invoke.request.checkStorage:invocation[0]'; disconnect: | 'done.invoke.request.clearingConnection:invocation[0]' - | 'done.invoke.request.reviewing.navigatingToHistory:invocation[0]'; + | 'done.invoke.request.reviewing.navigatingToHistory:invocation[0]' + | 'done.invoke.request.reviewing.navigatingToHome:invocation[0]'; monitorConnection: 'done.invoke.request:invocation[0]'; receiveVc: 'done.invoke.request.waitingForVc:invocation[0]'; requestBluetooth: 'done.invoke.request.checkingBluetoothService.requesting:invocation[0]'; @@ -148,6 +149,8 @@ export interface Typegen0 { | 'reviewing.idle' | 'reviewing.invalidIdentity' | 'reviewing.navigatingToHistory' + | 'reviewing.navigatingToHome' + | 'reviewing.navigatingToReceivedCards' | 'reviewing.rejected' | 'reviewing.savingFailed' | 'reviewing.savingFailed.idle' @@ -169,6 +172,8 @@ export interface Typegen0 { | 'idle' | 'invalidIdentity' | 'navigatingToHistory' + | 'navigatingToHome' + | 'navigatingToReceivedCards' | 'rejected' | 'savingFailed' | 'verifyingIdentity' diff --git a/machines/bleShare/request/selectors.ts b/machines/bleShare/request/selectors.ts index 44fef7c198..4ef2cc9fdf 100644 --- a/machines/bleShare/request/selectors.ts +++ b/machines/bleShare/request/selectors.ts @@ -58,3 +58,11 @@ export function selectIsSavingFailedInViewingVc(state: State) { export function selectIsDone(state: State) { return state.matches('reviewing.navigatingToHistory'); } + +export function selectIsNavigatingToReceivedCards(state: State) { + return state.matches('reviewing.navigatingToReceivedCards'); +} + +export function selectIsNavigatingToHome(state: State) { + return state.matches('reviewing.navigatingToHome'); +} diff --git a/machines/settings.typegen.ts b/machines/settings.typegen.ts index 376702a447..a67566d68a 100644 --- a/machines/settings.typegen.ts +++ b/machines/settings.typegen.ts @@ -25,6 +25,7 @@ export interface Typegen0 { }; 'eventsCausingActions': { injiTourGuide: + | 'ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS' | 'BACK' | 'CANCEL' | 'STORE_RESPONSE' diff --git a/routes/main.ts b/routes/main.ts index 96cf7e1cc7..8f54c56f31 100644 --- a/routes/main.ts +++ b/routes/main.ts @@ -9,9 +9,10 @@ import { RootStackParamList } from './index'; import { ScanLayout } from '../screens/Scan/ScanLayout'; import { HistoryScreen } from '../screens/History/HistoryScreen'; import i18n from '../i18n'; +import { BOTTOM_TAB_ROUTES } from './routesConstants'; const home: TabScreen = { - name: 'home', + name: BOTTOM_TAB_ROUTES.home, component: HomeScreen, icon: 'home', options: { @@ -24,7 +25,7 @@ const home: TabScreen = { }, }; export const scan: TabScreen = { - name: 'scan', + name: BOTTOM_TAB_ROUTES.scan, component: ScanLayout, icon: 'qr-code-scanner', options: { @@ -32,8 +33,9 @@ export const scan: TabScreen = { headerShown: false, }, }; + const history: TabScreen = { - name: 'history', + name: BOTTOM_TAB_ROUTES.history, component: HistoryScreen, icon: 'history', options: { @@ -48,11 +50,9 @@ mainRoutes.push(scan); mainRoutes.push(history); export type MainBottomTabParamList = { - home: { - activeTab: number; - }; - Scan: undefined; - History: undefined; + home: undefined; + scan: undefined; + history: undefined; }; export interface TabScreen { diff --git a/routes/routesConstants.ts b/routes/routesConstants.ts new file mode 100644 index 0000000000..03bcdcfeb2 --- /dev/null +++ b/routes/routesConstants.ts @@ -0,0 +1,29 @@ +import { MainBottomTabParamList } from './main'; + +export const BOTTOM_TAB_ROUTES = { + home: 'home' as keyof MainBottomTabParamList, + scan: 'scan' as keyof MainBottomTabParamList, + history: 'history' as keyof MainBottomTabParamList, +}; + +export const SCAN_ROUTES = { + ScanScreen: 'ScanScreen' as keyof ScanStackParamList, + SendVcScreen: 'SendVcScreen' as keyof ScanStackParamList, +}; + +export const REQUEST_ROUTES = { + Request: 'Request' as keyof RequestStackParamList, + RequestScreen: 'RequestScreen' as keyof RequestStackParamList, + ReceiveVcScreen: 'ReceiveVcScreen' as keyof RequestStackParamList, +}; + +export type ScanStackParamList = { + ScanScreen: undefined; + SendVcScreen: undefined; +}; + +export type RequestStackParamList = { + Request: undefined; + RequestScreen: undefined; + ReceiveVcScreen: undefined; +}; diff --git a/screens/Home/MyVcsTabController.ts b/screens/Home/MyVcsTabController.ts index ccc91c1269..1c9285eb08 100644 --- a/screens/Home/MyVcsTabController.ts +++ b/screens/Home/MyVcsTabController.ts @@ -18,7 +18,6 @@ import { MyVcsTabEvents, MyVcsTabMachine, selectAddVcModal, - selectIsOnboarding, selectIsRequestSuccessful, selectGetVcModal, selectIsSavingFailedInIdle, @@ -46,7 +45,6 @@ export function useMyVcsTab(props: HomeScreenTabProps) { isRefreshingVcs: useSelector(vcService, selectIsRefreshingMyVcs), isRequestSuccessful: useSelector(service, selectIsRequestSuccessful), - isOnboarding: useSelector(service, selectIsOnboarding), isSavingFailedInIdle: useSelector(service, selectIsSavingFailedInIdle), walletBindingError: useSelector(service, selectWalletBindingError), isBindingError: useSelector(service, selectShowWalletBindingError), @@ -70,8 +68,6 @@ export function useMyVcsTab(props: HomeScreenTabProps) { return service.send(MyVcsTabEvents.VIEW_VC(vcRef)); }, - ONBOARDING_DONE: () => service.send(MyVcsTabEvents.ONBOARDING_DONE()), - IS_TAMPERED: () => service.send(MyVcsTabEvents.IS_TAMPERED()), ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS: () => diff --git a/screens/Home/MyVcsTabMachine.ts b/screens/Home/MyVcsTabMachine.ts index 4532e267b9..684f79e0f3 100644 --- a/screens/Home/MyVcsTabMachine.ts +++ b/screens/Home/MyVcsTabMachine.ts @@ -11,10 +11,7 @@ import { StoreEvents, StoreResponseEvent } from '../../machines/store'; import { VcEvents } from '../../machines/vc'; import { vcItemMachine } from '../../machines/vcItem'; import { AppServices } from '../../shared/GlobalContext'; -import { - MY_VCS_STORE_KEY, - ONBOARDING_STATUS_STORE_KEY, -} from '../../shared/constants'; +import { MY_VCS_STORE_KEY } from '../../shared/constants'; import { AddVcModalMachine } from './MyVcs/AddVcModalMachine'; import { GetVcModalMachine } from './MyVcs/GetVcModalMachine'; import Storage from '../../shared/storage'; @@ -36,7 +33,6 @@ const model = createModel( GET_VC: () => ({}), STORAGE_AVAILABLE: () => ({}), STORAGE_UNAVAILABLE: () => ({}), - ONBOARDING_DONE: () => ({}), IS_TAMPERED: () => ({}), }, } @@ -57,31 +53,8 @@ export const MyVcsTabMachine = model.createMachine( events: {} as EventFrom, }, id: 'MyVcsTab', - initial: 'checkingOnboardingStatus', + initial: 'idle', states: { - checkingOnboardingStatus: { - entry: ['getOnboardingStatus'], - on: { - STORE_RESPONSE: [ - { cond: 'isOnboardingDone', target: 'idle' }, - { target: 'onboarding' }, - ], - }, - }, - onboarding: { - on: { - ADD_VC: [ - { - target: 'addVc', - actions: ['completeOnboarding'], - }, - ], - ONBOARDING_DONE: { - target: 'idle', - actions: ['completeOnboarding'], - }, - }, - }, addVc: { initial: 'checkStorage', states: { @@ -202,16 +175,6 @@ export const MyVcsTabMachine = model.createMachine( model.events.VIEW_VC(event.vcItemActor) ), - getOnboardingStatus: send( - () => StoreEvents.GET(ONBOARDING_STATUS_STORE_KEY), - { to: (context) => context.serviceRefs.store } - ), - - completeOnboarding: send( - () => StoreEvents.SET(ONBOARDING_STATUS_STORE_KEY, true), - { to: (context) => context.serviceRefs.store } - ), - storeVcItem: send( (_context, event) => { return StoreEvents.PREPEND( @@ -231,10 +194,6 @@ export const MyVcsTabMachine = model.createMachine( }, guards: { - isOnboardingDone: (_context, event: StoreResponseEvent) => { - return event.response === true; - }, - isMinimumStorageLimitReached: (_context, event) => Boolean(event.data), }, } @@ -257,10 +216,6 @@ export function selectGetVcModal(state: State) { return state.children.GetVcModal as ActorRefFrom; } -export function selectIsOnboarding(state: State) { - return state.matches('onboarding'); -} - export function selectIsRequestSuccessful(state: State) { return state.matches('addingVc.addVcSuccessful'); } diff --git a/screens/Home/MyVcsTabMachine.typegen.ts b/screens/Home/MyVcsTabMachine.typegen.ts index 513aa9ee5b..93a7314b59 100644 --- a/screens/Home/MyVcsTabMachine.typegen.ts +++ b/screens/Home/MyVcsTabMachine.typegen.ts @@ -30,8 +30,6 @@ export interface Typegen0 { services: never; }; 'eventsCausingActions': { - completeOnboarding: 'ADD_VC' | 'ONBOARDING_DONE'; - getOnboardingStatus: 'xstate.init'; refreshMyVc: 'IS_TAMPERED'; resetIsTampered: 'IS_TAMPERED'; sendVcAdded: 'STORE_RESPONSE'; @@ -41,7 +39,6 @@ export interface Typegen0 { 'eventsCausingDelays': {}; 'eventsCausingGuards': { isMinimumStorageLimitReached: 'done.invoke.MyVcsTab.addVc.checkStorage:invocation[0]'; - isOnboardingDone: 'STORE_RESPONSE'; }; 'eventsCausingServices': { AddVcModal: @@ -60,11 +57,9 @@ export interface Typegen0 { | 'addingVc.savingFailed.idle' | 'addingVc.storing' | 'addingVc.waitingForvcKey' - | 'checkingOnboardingStatus' | 'gettingVc' | 'gettingVc.waitingForvcKey' | 'idle' - | 'onboarding' | 'viewingVc' | { addVc?: 'checkStorage' | 'storageLimitReached'; diff --git a/screens/Request/RequestLayout.tsx b/screens/Request/RequestLayout.tsx index ad9cd3fdd6..de74ce8947 100644 --- a/screens/Request/RequestLayout.tsx +++ b/screens/Request/RequestLayout.tsx @@ -7,12 +7,15 @@ import { useRequestLayout } from './RequestLayoutController'; import { Message } from '../../components/Message'; import { ReceiveVcScreen } from './ReceiveVcScreen'; import { MessageOverlay } from '../../components/MessageOverlay'; - +import { ReceivedCardsModal } from '../Settings/ReceivedCardsModal'; +import { useReceivedVcsTab } from '../Home/ReceivedVcsTabController'; +import { REQUEST_ROUTES } from '../../routes/routesConstants'; const RequestStack = createNativeStackNavigator(); export const RequestLayout: React.FC = () => { const { t } = useTranslation('RequestScreen'); const controller = useRequestLayout(); + const receivedCardsController = useReceivedVcsTab(); return ( @@ -31,7 +34,7 @@ export const RequestLayout: React.FC = () => { }}> {!controller.isDone && ( { /> )} { /> + {controller.isAccepted && ( { - if (isDone) { - navigation.navigate('History'); + if (isNavigationToHome) { + navigation.navigate(BOTTOM_TAB_ROUTES.home); } else if (isReviewing) { - navigation.navigate('ReceiveVcScreen'); + navigation.navigate(REQUEST_ROUTES.ReceiveVcScreen); } else if (isWaitingForConnection) { - navigation.navigate('RequestScreen'); + navigation.navigate(REQUEST_ROUTES.RequestScreen); } - }, [isDone, isReviewing, isWaitingForConnection]); + }, [isNavigationToHome, isReviewing, isWaitingForConnection]); return { senderInfo: useSelector(requestService, selectSenderInfo), @@ -74,14 +83,13 @@ export function useRequestLayout() { isDisconnected: useSelector(requestService, selectIsDisconnected), isBleError: useSelector(requestService, selectIsHandlingBleError), bleError: useSelector(requestService, selectBleError), - IsSavingFailedInViewingVc: useSelector( requestService, selectIsSavingFailedInViewingVc ), isReviewing, isDone, - + isNavigatingToReceivedCards, DISMISS: () => requestService.send(RequestEvents.DISMISS()), RESET: () => requestService.send(RequestEvents.RESET()), }; diff --git a/screens/Request/RequestScreen.tsx b/screens/Request/RequestScreen.tsx index 7a4fbadef1..11b15cb0d4 100644 --- a/screens/Request/RequestScreen.tsx +++ b/screens/Request/RequestScreen.tsx @@ -15,6 +15,7 @@ import { useNavigation, } from '@react-navigation/native'; import { MainBottomTabParamList } from '../../routes/main'; +import { BOTTOM_TAB_ROUTES } from '../../routes/routesConstants'; type RequestStackParamList = { RequestScreen: undefined; @@ -56,7 +57,7 @@ export const RequestScreen: React.FC = () => { isVisible={controller.isMinimumStorageLimitReached} error="errors.storageLimitReached" onDismiss={() => { - navigation.navigate('Home'); + navigation.navigate(BOTTOM_TAB_ROUTES.home); }} translationPath="RequestScreen" /> diff --git a/screens/Scan/ScanLayout.tsx b/screens/Scan/ScanLayout.tsx index 84b11557a5..652788be6d 100644 --- a/screens/Scan/ScanLayout.tsx +++ b/screens/Scan/ScanLayout.tsx @@ -6,6 +6,7 @@ import { useScanLayout } from './ScanLayoutController'; import { ScanScreen } from './ScanScreen'; import { ProgressingModal } from '../../components/ProgressingModal'; import { MessageOverlay } from '../../components/MessageOverlay'; +import { SCAN_ROUTES } from '../../routes/routesConstants'; const ScanStack = createNativeStackNavigator(); @@ -18,7 +19,7 @@ export const ScanLayout: React.FC = () => { {!controller.isDone && ( { /> )} { if (isDone) { - navigation.navigate('home', { activeTab: 0 }); + navigation.navigate(BOTTOM_TAB_ROUTES.home); } else if (isReviewing) { - navigation.navigate('SendVcScreen'); + navigation.navigate(SCAN_ROUTES.SendVcScreen); } else if (isScanning) { - navigation.navigate('ScanScreen'); + navigation.navigate(SCAN_ROUTES.ScanScreen); } else if (isQrLoginDone) { - navigation.navigate('History'); + navigation.navigate(BOTTOM_TAB_ROUTES.history); } }, [isDone, isReviewing, isScanning, isQrLoginDone, isBleError]); diff --git a/screens/Scan/ScanScreen.tsx b/screens/Scan/ScanScreen.tsx index 88f28e216e..2ee75da447 100644 --- a/screens/Scan/ScanScreen.tsx +++ b/screens/Scan/ScanScreen.tsx @@ -11,12 +11,16 @@ import { QrLogin } from '../QrLogin/QrLogin'; import { useScanScreen } from './ScanScreenController'; import BluetoothStateManager from 'react-native-bluetooth-state-manager'; import { Linking, Platform } from 'react-native'; -import { useNavigation } from '@react-navigation/native'; +import { useNavigation, NavigationProp } from '@react-navigation/native'; +import { MainBottomTabParamList } from '../../routes/main'; +import { BOTTOM_TAB_ROUTES } from '../../routes/routesConstants'; export const ScanScreen: React.FC = () => { + type ScanScreenNavigation = NavigationProp; + const { t } = useTranslation('ScanScreen'); const controller = useScanScreen(); - const navigation = useNavigation(); + const navigation = useNavigation(); const [isBluetoothOn, setIsBluetoothOn] = useState(false); useEffect(() => { @@ -150,7 +154,7 @@ export const ScanScreen: React.FC = () => { } translationPath={'ScanScreen'} error="errors.storageLimitReached" - onDismiss={() => navigation.navigate('Home')} + onDismiss={() => navigation.navigate(BOTTOM_TAB_ROUTES.home)} /> ) ); diff --git a/screens/Settings/ReceivedCards.tsx b/screens/Settings/ReceivedCards.tsx index ec80045b27..67b9d710cc 100644 --- a/screens/Settings/ReceivedCards.tsx +++ b/screens/Settings/ReceivedCards.tsx @@ -1,15 +1,11 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { RefreshControl } from 'react-native'; import { Pressable } from 'react-native'; -import { Centered, Column, Text } from '../../components/ui'; -import { Icon } from 'react-native-elements'; +import { Column, Text } from '../../components/ui'; import { Theme } from '../../components/ui/styleUtils'; import { Image } from 'react-native'; -import { Modal } from '../../components/ui/Modal'; import { useReceivedVcsTab } from '../Home/ReceivedVcsTabController'; -import { VcItem } from '../../components/VcItem'; -import { ViewVcModal } from '../Home/ViewVcModal'; +import { ReceivedCardsModal } from './ReceivedCardsModal'; export const ReceivedCards: React.FC = () => { const { t } = useTranslation('ReceivedVcsTab'); @@ -30,68 +26,11 @@ export const ReceivedCards: React.FC = () => { - - } - headerTitle={t('header')} - headerElevation={2} - onDismiss={controller.TOGGLE_RECEIVED_CARDS}> - - }> - {controller.vcKeys.map((vcKey) => ( - - ))} - {controller.vcKeys.length === 0 && ( - - - - - {t('noReceivedVcsTitle')} - - - {t('noReceivedVcsText')} - - - - )} - - {controller.selectedVc && ( - { - controller.REVOKE(); - }} - activeTab={controller.activeTab} - /> - )} - + controller={controller} + onDismiss={controller.TOGGLE_RECEIVED_CARDS} + /> ); }; diff --git a/screens/Settings/ReceivedCardsModal.tsx b/screens/Settings/ReceivedCardsModal.tsx new file mode 100644 index 0000000000..5224f8b8a4 --- /dev/null +++ b/screens/Settings/ReceivedCardsModal.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { RefreshControl } from 'react-native'; +import { Centered, Column, Text } from '../../components/ui'; +import { Icon } from 'react-native-elements'; +import { Theme } from '../../components/ui/styleUtils'; +import { Modal } from '../../components/ui/Modal'; +import { VcItem } from '../../components/VcItem'; +import { ViewVcModal } from '../Home/ViewVcModal'; + +export const ReceivedCardsModal: React.FC = ({ + isVisible, + controller, + onDismiss, +}) => { + const { t } = useTranslation('ReceivedVcsTab'); + return ( + } + headerTitle={t('header')} + headerElevation={2} + onDismiss={onDismiss}> + + }> + {controller.vcKeys.map((vcKey) => ( + + ))} + {controller.vcKeys.length === 0 && ( + + + + + {t('noReceivedVcsTitle')} + + + {t('noReceivedVcsText')} + + + + )} + + {controller.selectedVc && ( + { + controller.REVOKE(); + }} + activeTab={controller.activeTab} + /> + )} + + ); +}; + +export interface ReceivedCardsProps { + isVisible: boolean; + controller: any; + onDismiss: () => void; +} diff --git a/screens/Settings/SettingScreenController.ts b/screens/Settings/SettingScreenController.ts index 392ca71520..0b5394a7fe 100644 --- a/screens/Settings/SettingScreenController.ts +++ b/screens/Settings/SettingScreenController.ts @@ -28,6 +28,7 @@ import { GlobalContext } from '../../shared/GlobalContext'; import { useTranslation } from 'react-i18next'; import { Platform } from 'react-native'; import { RequestRouteProps, RootRouteProps } from '../../routes'; +import { REQUEST_ROUTES } from '../../routes/routesConstants'; export function useSettingsScreen(props: RootRouteProps & RequestRouteProps) { const { appService } = useContext(GlobalContext); @@ -139,7 +140,7 @@ export function useSettingsScreen(props: RootRouteProps & RequestRouteProps) { ), RECEIVE_CARD: () => { - props.navigation.navigate('Request'); + props.navigation.navigate(REQUEST_ROUTES.Request); setIsVisible(false); }, diff --git a/shared/constants.ts b/shared/constants.ts index f60f8ddc37..8681562f4f 100644 --- a/shared/constants.ts +++ b/shared/constants.ts @@ -43,8 +43,6 @@ export const ACTIVITY_LOG_STORE_KEY = 'activityLog'; export const SETTINGS_STORE_KEY = 'settings'; -export const ONBOARDING_STATUS_STORE_KEY = 'isOnboardingDone'; - export const GNM_API_KEY = GOOGLE_NEARBY_MESSAGES_API_KEY; // https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Message#MAX_CONTENT_SIZE_BYTES