diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index a3389ed4d8..e581d444b7 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/setup-python@v4 with: - python-version: '3.11' + python-version: '3.11' - name: Setup NodeJS uses: ./.github/actions/setup-node @@ -47,7 +47,7 @@ jobs: - uses: actions/setup-python@v4 with: - python-version: '3.11' + python-version: '3.11' - name: Setup NodeJS uses: ./.github/actions/setup-node @@ -65,3 +65,4 @@ jobs: yarn run test:coverage - uses: codecov/codecov-action@v3 + if: always() diff --git a/packages/legacy/core/App/components/misc/NewQRView.tsx b/packages/legacy/core/App/components/misc/NewQRView.tsx index 459c739787..90ccb41c42 100644 --- a/packages/legacy/core/App/components/misc/NewQRView.tsx +++ b/packages/legacy/core/App/components/misc/NewQRView.tsx @@ -48,12 +48,9 @@ const NewQRView: React.FC = ({ defaultToConnect, handleCodeScan, error, e container: { flex: 1, backgroundColor: ColorPallet.brand.secondaryBackground, - justifyContent: 'space-between', - alignItems: 'center', }, camera: { flex: 1, - width: '100%', justifyContent: 'center', alignItems: 'center', }, diff --git a/packages/legacy/core/App/components/misc/QRScanner.tsx b/packages/legacy/core/App/components/misc/QRScanner.tsx index 40d10a19b4..7247ebe82a 100644 --- a/packages/legacy/core/App/components/misc/QRScanner.tsx +++ b/packages/legacy/core/App/components/misc/QRScanner.tsx @@ -1,15 +1,17 @@ import { useNavigation } from '@react-navigation/core' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' -import { Vibration, View, StyleSheet, Text } from 'react-native' +import { View, Modal, Vibration, Pressable, StyleSheet, Text } from 'react-native' import { BarCodeReadEvent, RNCamera } from 'react-native-camera' -import Icon from 'react-native-vector-icons/MaterialIcons' +import Icon from 'react-native-vector-icons/MaterialCommunityIcons' +import { hitSlop } from '../../constants' import { useTheme } from '../../contexts/theme' import { QrCodeScanError } from '../../types/error' +import { Screens } from '../../types/navigators' import { testIdWithKey } from '../../utils/testable' +import InfoBox, { InfoBoxType } from '../misc/InfoBox' -import QRScannerClose from './QRScannerClose' import QRScannerTorch from './QRScannerTorch' interface Props { @@ -18,31 +20,17 @@ interface Props { enableCameraOnError?: boolean } -const CameraViewContainer: React.FC = ({ children }) => { - return ( - - {children} - - ) -} - const QRScanner: React.FC = ({ handleCodeScan, error, enableCameraOnError }) => { const navigation = useNavigation() const [cameraActive, setCameraActive] = useState(true) const [torchActive, setTorchActive] = useState(false) + const [showInfoBox, setShowInfoBox] = useState(false) const { t } = useTranslation() const invalidQrCodes = new Set() const { ColorPallet, TextTheme } = useTheme() const styles = StyleSheet.create({ container: { - height: '100%', - width: '100%', + flex: 1, }, viewFinder: { width: 250, @@ -52,7 +40,7 @@ const QRScanner: React.FC = ({ handleCodeScan, error, enableCameraOnError borderColor: ColorPallet.grayscale.white, }, viewFinderContainer: { - flex: 1, + flexGrow: 1, justifyContent: 'center', alignItems: 'center', }, @@ -66,8 +54,30 @@ const QRScanner: React.FC = ({ handleCodeScan, error, enableCameraOnError }, }) + const styleForState = ({ pressed }: { pressed: boolean }) => [{ opacity: pressed ? 0.2 : 1 }] + + const toggleShowInfoBox = () => setShowInfoBox(!showInfoBox) + return ( + + + + + = ({ handleCodeScan, error, enableCameraOnError if (invalidQrCodes.has(event.data)) { return } + if (error?.data === event?.data) { invalidQrCodes.add(error.data) if (enableCameraOnError) { return setCameraActive(true) } } + if (cameraActive) { Vibration.vibrate() handleCodeScan(event) + return setCameraActive(false) } }} > - - navigation.goBack()}> + {error ? ( <> - + = ({ handleCodeScan, error, enableCameraOnError )} + + + + A valid QR code will scan automatically. + + - setTorchActive(!torchActive)} /> - + + + + + + + navigation.navigate(Screens.ScanHelp)} + style={styleForState} + hitSlop={hitSlop} + > + + + + setTorchActive(!torchActive)} /> + + ) diff --git a/packages/legacy/core/App/components/misc/QRScannerClose.tsx b/packages/legacy/core/App/components/misc/QRScannerClose.tsx deleted file mode 100644 index b0d2a34775..0000000000 --- a/packages/legacy/core/App/components/misc/QRScannerClose.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react' -import { useTranslation } from 'react-i18next' -import { StyleSheet, TouchableOpacity, View } from 'react-native' -import Icon from 'react-native-vector-icons/MaterialIcons' - -import { hitSlop } from '../../constants' -import { useTheme } from '../../contexts/theme' -import { testIdWithKey } from '../../utils/testable' - -interface Props { - onPress?: () => void -} - -const CloseButton: React.FC = ({ onPress }) => { - const { t } = useTranslation() - const { ColorPallet } = useTheme() - const styles = StyleSheet.create({ - container: { - width: '100%', - flexDirection: 'row', - justifyContent: 'flex-end', - }, - button: { - padding: 16, - }, - }) - return ( - - - - - - ) -} - -const QRScannerClose: React.FC = ({ onPress }) => { - return -} - -export default QRScannerClose diff --git a/packages/legacy/core/App/components/misc/QRScannerTorch.tsx b/packages/legacy/core/App/components/misc/QRScannerTorch.tsx index 298192f4be..c5c264a693 100644 --- a/packages/legacy/core/App/components/misc/QRScannerTorch.tsx +++ b/packages/legacy/core/App/components/misc/QRScannerTorch.tsx @@ -16,8 +16,8 @@ interface Props extends React.PropsWithChildren { function createStyles({ ColorPallet }: ITheme) { return StyleSheet.create({ container: { - width: 48, - height: 48, + width: 24, + height: 24, justifyContent: 'center', alignItems: 'center', borderWidth: 1, @@ -35,6 +35,7 @@ const TorchButton: React.FC = ({ active, onPress, children }) => { const { t } = useTranslation() const theme = useTheme() const styles = createStyles(theme) + return ( void + testID?: string } -const Link: React.FC = ({ linkText, onPress, style = {}, ...textProps }) => { +const Link: React.FC = ({ linkText, onPress, style = {}, testID, ...textProps }) => { const { TextTheme, ColorPallet } = useTheme() const styles = StyleSheet.create({ link: { @@ -21,13 +22,14 @@ const Link: React.FC = ({ linkText, onPress, style = {}, ...textProps alignSelf: 'flex-start', }, }) + return ( diff --git a/packages/legacy/core/App/constants.ts b/packages/legacy/core/App/constants.ts index 13527f2ded..0682eb1dcb 100644 --- a/packages/legacy/core/App/constants.ts +++ b/packages/legacy/core/App/constants.ts @@ -1,9 +1,12 @@ import { PINValidationRules } from './types/security' -export const dateIntFormat = 'YYYYMMDD' - const lengthOfhiddenAttributes = 10 const unicodeForBulletCharacter = '\u2022' + +export const whereToUseWalletUrl = 'http://example.com' + +export const dateIntFormat = 'YYYYMMDD' + export const hiddenFieldValue = Array(lengthOfhiddenAttributes).fill(unicodeForBulletCharacter).join('') // Used to property prefix TestIDs so they can be looked up // by on-device automated testing systems like SauceLabs. diff --git a/packages/legacy/core/App/localization/en/index.ts b/packages/legacy/core/App/localization/en/index.ts index 5299372395..0cd1267e0d 100644 --- a/packages/legacy/core/App/localization/en/index.ts +++ b/packages/legacy/core/App/localization/en/index.ts @@ -350,7 +350,16 @@ const translation = { "MyQRCode": "My QR code", "UnableToHandleRedirection": "Unable to handle redirection", "Close": "Close", - "Torch": "Flash" + "Torch": "Flash", + "ScanHelp": "Scan Help", + "ScanNow": "Scan Now", + "WhatToScan": "What QR Codes can be scanned?", + "ScanOnySpecial": "Only special QR codes can be scanned by Bifold Wallet.", + "ScanOnlySpecial2": "These are presented by participating services or people to receive a credential offer, request for information or to connect.", + "ScanOnlySpecial3": "Bifold Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones.", + "WhereToUseLink": "See where you can use Bifold Wallet", + "BadQRCode": "QR Code Not Recognized", + "BadQRCodeDescription": "Ths QR code scanned doesn't work with Bifold Wallet. Bifold Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones.", }, "Connection": { "JustAMoment": "Just a moment while we make a secure connection...", diff --git a/packages/legacy/core/App/localization/fr/index.ts b/packages/legacy/core/App/localization/fr/index.ts index 47a8605a7a..9b6d0351b6 100644 --- a/packages/legacy/core/App/localization/fr/index.ts +++ b/packages/legacy/core/App/localization/fr/index.ts @@ -349,7 +349,15 @@ const translation = { "MyQRCode": "My QR code (FR)", "UnableToHandleRedirection": "Impossible de traiter la redirection", "Close": "Fermer", - "Torch": "Flash" + "Torch": "Flash", + "ScanHelp": "Scan Help (FR)", + "ScanNow": "Scan Now (FR)", + "ScanOnySpecial": "Only special QR codes can be scanned by Bifold Wallet. (FR)", + "ScanOnlySpecial2": "These are presented by participating services or people to receive a credential offer, request for information or to connect. (FR)", + "ScanOnlySpecial3": "Bifold Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones. (FR)", + "WhereToUseLink": "See where you can use Bifold Wallet (FR)", + "BadQRCode": "QR Code Not Recognized (FR)", + "BadQRCodeDescription": "Ths QR code scanned doesn't work with Bifold Wallet. Bifold Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones. (FR)", }, "Connection": { "JustAMoment": "Veuillez patienter pendant que nous établissons une connexion sécurisée...", diff --git a/packages/legacy/core/App/localization/pt-br/index.ts b/packages/legacy/core/App/localization/pt-br/index.ts index 2111621607..7488ccbb29 100644 --- a/packages/legacy/core/App/localization/pt-br/index.ts +++ b/packages/legacy/core/App/localization/pt-br/index.ts @@ -329,7 +329,15 @@ const translation = { "MyQRCode": "Meu QR code", "UnableToHandleRedirection": "Não foi possível tratar redirecionamento", "Close": "Fechar", - "Torch": "Flash" + "Torch": "Flash", + "ScanHelp": "Scan Help (PB)", + "ScanNow": "Scan Now (PB)", + "ScanOnySpecial": "Only special QR codes can be scanned by Bifold Wallet. (PB)", + "ScanOnlySpecial2": "These are presented by participating services or people to receive a credential offer, request for information or to connect. (PB)", + "ScanOnlySpecial3": "Bifold Wallet currently doesn't support adding digital credential by scanning or taking photos of physical ones. (PB)", + "WhereToUseLink": "See where you can use Bifold Wallet (PB)", + "BadQRCode": "QR Code Not Recognized (PB)", + "BadQRCodeDescription": "Ths QR code scanned doesn't work with Bifold Wallet. Bifold Wallet only works with participating services.\n\nIt currently can't add digital credentials by taking photos of physical ones. (PB)", }, "Connection": { "JustAMoment": "Aguarde um momento enquanto fazemos uma conexão segura...", diff --git a/packages/legacy/core/App/navigators/ConnectStack.tsx b/packages/legacy/core/App/navigators/ConnectStack.tsx index 92e8e5b1d2..d88c1fa5d3 100644 --- a/packages/legacy/core/App/navigators/ConnectStack.tsx +++ b/packages/legacy/core/App/navigators/ConnectStack.tsx @@ -3,9 +3,9 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { useConfiguration } from '../contexts/configuration' -import { useStore } from '../contexts/store' import { useTheme } from '../contexts/theme' import NameWallet from '../screens/NameWallet' +import ScanHelp from '../screens/ScanHelp' import { ConnectStackParams, Screens } from '../types/navigators' import { testIdWithKey } from '../utils/testable' @@ -17,17 +17,22 @@ const ConnectStack: React.FC = () => { const defaultStackOptions = createDefaultStackOptions(theme) const { scan } = useConfiguration() const { t } = useTranslation() - const [store] = useStore() + return ( + ) diff --git a/packages/legacy/core/App/navigators/RootStack.tsx b/packages/legacy/core/App/navigators/RootStack.tsx index c2b5c107f9..e2c1693ca9 100644 --- a/packages/legacy/core/App/navigators/RootStack.tsx +++ b/packages/legacy/core/App/navigators/RootStack.tsx @@ -263,12 +263,7 @@ const RootStack: React.FC = () => { ), })} /> - + { + const { t } = useTranslation() + + const { TextTheme } = useTheme() + const style = StyleSheet.create({ + safeArea: { + flex: 1, + }, + scrollView: { + flexGrow: 1, + paddingHorizontal: 26, + }, + text: { + ...TextTheme.normal, + marginTop: 15, + }, + }) + + return ( + + + {t('Scan.WhatToScan')} + {t('Scan.ScanOnySpecial')} + {t('Scan.ScanOnlySpecial2')} + Linking.openURL(whereToUseWalletUrl)} + testID={testIdWithKey('WhereToUseLink')} + /> + {t('Scan.ScanOnlySpecial3')} + + + ) +} + +export default ScanHelp diff --git a/packages/legacy/core/App/types/navigators.ts b/packages/legacy/core/App/types/navigators.ts index b619656e5a..72ebb0bdcf 100644 --- a/packages/legacy/core/App/types/navigators.ts +++ b/packages/legacy/core/App/types/navigators.ts @@ -37,6 +37,7 @@ export enum Screens { ProofDetails = 'Proof Details', NameWallet = 'Name Wallet', RenameContact = 'Rename Contact', + ScanHelp = 'Scan Help', } export enum Stacks { @@ -128,6 +129,7 @@ export type HomeStackParams = { export type ConnectStackParams = { [Screens.Scan]: undefined [Screens.NameWallet]: undefined + [Screens.ScanHelp]: undefined } export type SettingStackParams = { diff --git a/packages/legacy/core/__tests__/components/__snapshots__/NewQRView.test.tsx.snap b/packages/legacy/core/__tests__/components/__snapshots__/NewQRView.test.tsx.snap index 59c05d79c2..f03763aa8e 100644 --- a/packages/legacy/core/__tests__/components/__snapshots__/NewQRView.test.tsx.snap +++ b/packages/legacy/core/__tests__/components/__snapshots__/NewQRView.test.tsx.snap @@ -11,10 +11,8 @@ exports[`NewQRView Component Renders correctly on first tab 1`] = ` } style={ Object { - "alignItems": "center", "backgroundColor": "#313132", "flex": 1, - "justifyContent": "space-between", } } > @@ -200,10 +198,8 @@ exports[`NewQRView Component Renders correctly on second tab 1`] = ` } style={ Object { - "alignItems": "center", "backgroundColor": "#313132", "flex": 1, - "justifyContent": "space-between", } } > diff --git a/packages/legacy/core/__tests__/screens/ScanHelp.test.tsx b/packages/legacy/core/__tests__/screens/ScanHelp.test.tsx new file mode 100644 index 0000000000..90ccace27d --- /dev/null +++ b/packages/legacy/core/__tests__/screens/ScanHelp.test.tsx @@ -0,0 +1,29 @@ +import { fireEvent, render } from '@testing-library/react-native' +import React from 'react' + +import ScanHelp from '../../App/screens/ScanHelp' +import { testIdWithKey } from '../../App/utils/testable' + +jest.mock('@react-navigation/core', () => { + return require('../../__mocks__/custom/@react-navigation/core') +}) +jest.mock('@react-navigation/native', () => { + return require('../../__mocks__/custom/@react-navigation/native') +}) + +describe('ScanHelp Screen', () => { + test('Renders correctly', async () => { + const tree = render() + expect(tree).toMatchSnapshot() + }) + + test('Link button exists and is accessible', async () => { + const tree = render() + const { getByTestId } = tree + const linkButton = getByTestId(testIdWithKey('WhereToUseLink')) + + fireEvent(linkButton, 'press') + + expect(linkButton).toBeTruthy() + }) +}) diff --git a/packages/legacy/core/__tests__/screens/__snapshots__/ScanHelp.test.tsx.snap b/packages/legacy/core/__tests__/screens/__snapshots__/ScanHelp.test.tsx.snap new file mode 100644 index 0000000000..9437efca31 --- /dev/null +++ b/packages/legacy/core/__tests__/screens/__snapshots__/ScanHelp.test.tsx.snap @@ -0,0 +1,109 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ScanHelp Screen Renders correctly 1`] = ` + + + + + Scan.WhatToScan + + + Scan.ScanOnySpecial + + + Scan.ScanOnlySpecial2 + + + Scan.WhereToUseLink + + + Scan.ScanOnlySpecial3 + + + + +`;