Skip to content

Commit

Permalink
UIT-32: Add camera functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
hstandaert committed Nov 22, 2022
1 parent 94c6d21 commit 7e31e32
Show file tree
Hide file tree
Showing 26 changed files with 341 additions and 64 deletions.
3 changes: 2 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
android:exported="true"
android:screenOrientation="portrait">
</activity>
</application>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import com.visioncameradynamsoftbarcodereader.VisionCameraDynamsoftBarcodeReaderPackage;

public class MainApplication extends Application implements ReactApplication {

Expand All @@ -30,6 +31,7 @@ protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new VisionCameraDynamsoftBarcodeReaderPackage());
return packages;
}

Expand Down
6 changes: 5 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
module.exports = {
plugins: ['react-native-reanimated/plugin'], // reanimated must be the last package
plugins: [
['react-native-reanimated/plugin', { // reanimated must be the last package
globals: ['__decode'],
}]
],
presets: ['module:metro-react-native-babel-preset'],
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Uitpas Beta.app"
BuildableName = "Uitpas Debug.app"
BlueprintName = "reactnative_uitpas"
ReferencedContainer = "container:reactnative_uitpas.xcodeproj">
</BuildableReference>
Expand All @@ -33,7 +33,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Uitpas Beta.app"
BuildableName = "Uitpas Debug.app"
BlueprintName = "reactnative_uitpas"
ReferencedContainer = "container:reactnative_uitpas.xcodeproj">
</BuildableReference>
Expand Down Expand Up @@ -73,7 +73,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Uitpas Beta.app"
BuildableName = "Uitpas Debug.app"
BlueprintName = "reactnative_uitpas"
ReferencedContainer = "container:reactnative_uitpas.xcodeproj">
</BuildableReference>
Expand All @@ -90,7 +90,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Uitpas Beta.app"
BuildableName = "Uitpas Debug.app"
BlueprintName = "reactnative_uitpas"
ReferencedContainer = "container:reactnative_uitpas.xcodeproj">
</BuildableReference>
Expand Down
40 changes: 21 additions & 19 deletions ios/reactnative_uitpas/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,35 @@
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>CFBundleURLName</key>
<string>auth0</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>itms-apps</string>
</array>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(REACT_NATIVE_APP_VERSION_NR)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>CFBundleURLName</key>
<string>auth0</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>7</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>itms-apps</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
Expand Down Expand Up @@ -80,8 +80,10 @@
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
"react-native-screens": "^3.18.2",
"react-native-splash-screen": "^3.3.0",
"react-native-svg": "^13.6.0",
"styled-components": "^5.3.6"
"react-native-vision-camera": "^2.15.2",
"styled-components": "^5.3.6",
"vision-camera-dynamsoft-barcode-reader": "^0.4.4"
},
"devDependencies": {
"@babel/core": "^7.12.9",
Expand Down
1 change: 1 addition & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import RootStackNavigator from './_routing';
import { theme } from './_styles/theme';
import { storage } from './storage';

import 'react-native-reanimated';
import './_translations/i18n';

LogBox.ignoreAllLogs();
Expand Down
Binary file added src/_assets/icons/QRInstruction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_assets/icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_assets/icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/_assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export const Logout = require('./logout.png');
export const Gift = require('./gift.png');
export const Info = require('./info.png');
export const External = require('./external.png');
export const QRInstruction = require('./QRInstruction.png');
2 changes: 1 addition & 1 deletion src/_components/button/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const ButtonText = styled(Typography)<{
if ($variant === 'link') {
return $active ? theme.colors.turquoiseActive : theme.colors.turquoise;
} else if ($variant === 'outline') {
return theme.colors.turquoise;
return theme.colors.white;
}
return theme.colors.white;
Expand Down
8 changes: 7 additions & 1 deletion src/_config/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ type TConfigUrlIdentifiers =
| 'privacyPolicy'
| 'shop'
| 'appStore'
| 'playStore';
| 'playStore'
| 'scanHelp';

const urls: Record<TConfigUrlIdentifiers, TConfigUrl> = {
appStore: {
Expand Down Expand Up @@ -41,6 +42,11 @@ const urls: Record<TConfigUrlIdentifiers, TConfigUrl> = {
beta: 'https://test.uitpas.be/uitid-registreren-stap1',
production: 'https://uitpas.be/uitid-registreren-stap1',
},
scanHelp: {
beta: 'https://helpdesk.uitpas.be/hc/nl/articles/360010576839-Hoe-kan-ik-punten-sparen-?utm_source=uitpas-app&utm_medium=uitpas-app&utm_campaign=uitpas-app&utm_content=scherm-punten-sparen',
production:
'https://helpdesk.uitpas.be/hc/nl/articles/360010576839-Hoe-kan-ik-punten-sparen-?utm_source=uitpas-app&utm_medium=uitpas-app&utm_campaign=uitpas-app&utm_content=scherm-punten-sparen',
},
shop: {
beta: 'https://test.uitpas.be/voordelen-zoeken?cardSystemsFilter[0]={{cardSystem}}&utm_source=uitpas-app&utm_medium=uitpas-app&utm_campaign=uitpas-app&utm_content=open-shop',
production:
Expand Down
18 changes: 0 additions & 18 deletions src/_routing/_components/AuthenticationNavigator.tsx

This file was deleted.

8 changes: 4 additions & 4 deletions src/_routing/_components/MainNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { t } from 'i18next';

import TabBarIcon from '../../_components/tabBarIcon/TabBarIcon';
import { theme } from '../../_styles/theme';
import Scan from '../../scan/Scan';
import Shop from '../../shop/Shop';
import { ProfileNavigator } from './ProfileNavigator';
import { ScanNavigator } from './ScanNavigator';
import { mapRouteNameToIcon } from './utils';

export type TMainRoutes = 'ProfileNavigator' | 'Scan' | 'Shop';
export type TMainRoutes = 'ProfileNavigator' | 'ScanNavigator' | 'Shop';
export type TMainParams = Record<TMainRoutes, undefined>;

export const MainNavigator: FC = () => {
Expand Down Expand Up @@ -41,8 +41,8 @@ export const MainNavigator: FC = () => {
}}
/>
<Tab.Screen
component={Scan}
name="Scan"
component={ScanNavigator}
name="ScanNavigator"
options={{
title: t('NAVIGATION.SCAN'),
}}
Expand Down
17 changes: 17 additions & 0 deletions src/_routing/_components/ScanNavigator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { FC } from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import Camera from '../../scan/camera/Camera';

export type TScanRoutes = 'Camera';
export type TScanParams = Record<TScanRoutes, undefined>;

const Stack = createNativeStackNavigator<TScanParams>();

export const ScanNavigator: FC = () => {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen component={Camera} name="Camera" />
</Stack.Navigator>
);
};
4 changes: 4 additions & 0 deletions src/_translations/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,9 @@
"SHOP": {
"DESCRIPTION": "Met je gespaarde punten kan je heel wat voordelen omruilen. Doorzoek de voordelen op zoek naar een korting, gadget of cadeau dat bij jou past.",
"BUTTON": "Ga naar de shop"
},
"CAMERA": {
"DESCRIPTION": "Scan de UiTPAS QR-code",
"CTA": "Hulp nodig met scannen?"
}
}
4 changes: 2 additions & 2 deletions src/profile/LogOutModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const LogoutModal: FC<TLogOutModalProps> = ({ isVisible, toggleIsVisible }) => {
</Styled.TitleText>
<Typography>{t('AUTHENTICATION.CONFIRM_TEXT')}</Typography>
<Styled.ButtonContainer>
<Styled.ActionButton label={t('AUTHENTICATION.CANCEL')} onPress={toggleIsVisible} variant="outline" />
<Styled.ActionButton label={t('AUTHENTICATION.CONFIRM')} onPress={handleLogout} variant="outline" />
<Styled.ActionButton label={t('AUTHENTICATION.CANCEL')} onPress={toggleIsVisible} underline={false} variant="link" />
<Styled.ActionButton label={t('AUTHENTICATION.CONFIRM')} onPress={handleLogout} underline={false} variant="link" />
</Styled.ButtonContainer>
</BlurredModal>
);
Expand Down
12 changes: 0 additions & 12 deletions src/scan/Scan.tsx

This file was deleted.

1 change: 1 addition & 0 deletions src/scan/_hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useCameraPermission';
21 changes: 21 additions & 0 deletions src/scan/_hooks/useCameraPermission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useEffect, useState } from 'react';
import { Camera } from 'react-native-vision-camera';

export function useCameraPermission() {
const [hasCameraPermission, setHasCameraPermission] = useState<boolean>();

useEffect(() => {
(async () => {
let permission = await Camera.getCameraPermissionStatus();
if (permission !== 'authorized') {
permission = await Camera.requestCameraPermission();
}

setHasCameraPermission(permission === 'authorized');
})();
}, []);

return {
hasCameraPermission,
};
}
68 changes: 68 additions & 0 deletions src/scan/_hooks/useOverlayDimensions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useMemo } from 'react';
import { PixelRatio } from 'react-native';
import { Rect } from 'vision-camera-code-scanner';

type Corner = {
path: string;
x: number;
y: number;
};

export type TOverlayDimensions = {
cornerLength: number;
padding: number;
strokeWidth: number;
};

export function useOverlayDimensions(dimensions, { padding, strokeWidth, cornerLength }: TOverlayDimensions) {
const [width, height] = dimensions;
const pixelRatio = PixelRatio.get();

return useMemo(() => {
const sideLength = width - padding * 2;
const boundingBox: Partial<Rect> = {};

boundingBox.left = (width - sideLength) / 2;
boundingBox.right = boundingBox.left + sideLength;
boundingBox.top = (height - sideLength) / 2;
boundingBox.bottom = boundingBox.top + sideLength;

const corners: Corner[] = [
{
path: `M 0 ${cornerLength} L 0 0 L ${cornerLength} 0`,
x: boundingBox.left + strokeWidth / 2,
y: boundingBox.top + strokeWidth / 2,
},
{
path: `M 0 0 L ${cornerLength} 0 L ${cornerLength} ${cornerLength}`,
x: boundingBox.right - cornerLength - strokeWidth / 2,
y: boundingBox.top + strokeWidth / 2,
},
{
path: `M ${cornerLength} 0 L ${cornerLength} ${cornerLength} L 0 ${cornerLength}`,
x: boundingBox.right - cornerLength - strokeWidth / 2,
y: boundingBox.bottom - cornerLength - strokeWidth / 2,
},
{
path: `M 0 0 L 0 ${cornerLength} L ${cornerLength} ${cornerLength}`,
x: boundingBox.left + strokeWidth / 2,
y: boundingBox.bottom - cornerLength - strokeWidth / 2,
},
];

/* @see https://www.dynamsoft.com/barcode-reader/docs/core/parameters/reference/region-definition/index.html?ver=latest#image-process-control */
const regionDefinition = {
Bottom: Math.round((boundingBox.bottom / height) * 100),
Left: Math.round((boundingBox.left / width) * 100),
Right: Math.round((boundingBox.right / width) * 100),
Top: Math.round((boundingBox.top / height) * 100),
};

return {
boundingBox: boundingBox as Rect,
corners,
regionDefinition,
sideLength,
};
}, [width, height, pixelRatio]);
}
Loading

0 comments on commit 7e31e32

Please sign in to comment.