Skip to content

Commit

Permalink
Merge pull request #18 from trajano/pdf-view
Browse files Browse the repository at this point in the history
Pdf and Nfc
  • Loading branch information
trajano authored Nov 22, 2024
2 parents 672e422 + 1ca5211 commit a13b276
Show file tree
Hide file tree
Showing 47 changed files with 2,398 additions and 265 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ The following tools were evaluated but eventually replaced:
- **[Bun](https://bun.sh/)**: Discontinued due to file-locking issues on Windows.
- **[Lefthook](https://github.com/evilmartians/lefthook)**: Originally used but replaced with [Husky](https://typicode.github.io/husky) and [lint-staged](https://github.com/okonet/lint-staged) for simplicity.
- **[create-react-native-library](https://github.com/callstack/react-native-builder-bob)**: Dropped due to its complexity and a preference for more streamlined approaches.
- **[expo-module-scripts](https://www.npmjs.com/package/expo-module-scripts)**: Does not work in Windows. https://github.com/expo/expo/issues/30897

## Shell Scripts

Expand Down
815 changes: 587 additions & 228 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
"react-native": "0.74.5"
},
"devDependencies": {
"@commitlint/cli": "^19.5.0",
"@commitlint/config-conventional": "^19.5.0",
"@commitlint/cli": "^19.6.0",
"@commitlint/config-conventional": "^19.6.0",
"@commitlint/types": "^19.5.0",
"husky": "^9.1.6",
"husky": "^9.1.7",
"jest": "^29.7.0",
"lint-staged": "^15.2.10",
"patch-package": "^8.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/my-app-appium-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@
"dist/"
],
"dependencies": {
"webdriverio": "^9.2.14"
"webdriverio": "^9.3.0"
}
}
6 changes: 6 additions & 0 deletions packages/my-app/__mocks__/react-native-nfc-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const start = jest.fn(() => Promise.resolve());
export const isSupported = jest.fn(() => Promise.resolve(true));
export default {
start,
isSupported,
};
4 changes: 4 additions & 0 deletions packages/my-app/app.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://json.schemastore.org/expo-50.0.0.json#",
"expo": {
"name": "My App Go",
"slug": "my-app",
Expand Down Expand Up @@ -41,6 +42,7 @@
},
"plugins": [
"expo-router",
["expo-asset", {}],
"expo-background-fetch",
[
"expo-font",
Expand Down Expand Up @@ -69,6 +71,8 @@
"expo-tracking-transparency",
"expo-video",
"@config-plugins/android-jsc-intl",
"@config-plugins/react-native-blob-util",
"@config-plugins/react-native-pdf",
"react-native-nfc-manager"
],
"experiments": {
Expand Down
54 changes: 27 additions & 27 deletions packages/my-app/metro.config.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
// @ts-check
// @ts-nocheck
/* eslint-env node */
const { getDefaultConfig } = require('expo/metro-config');
const { mergeConfig } = require('metro-config');
const withStorybook = require('@storybook/react-native/metro/withStorybook');
const path = require('path');

const monorepoRoot = path.resolve(__dirname, '../..');

const config = getDefaultConfig(__dirname);
let config = getDefaultConfig(__dirname);

config.watchFolders = [monorepoRoot];
config.resolver.nodeModulesPaths = [
...config.resolver.nodeModulesPaths,
path.resolve(__dirname, 'node_modules'),
path.resolve(monorepoRoot, 'node_modules'),
];
const additionalAssetExts = ['lottie', 'fbx'];
config.resolver.assetExts = [
...config.resolver.assetExts,
...additionalAssetExts,
];
const testRegexs = [/^.*\/[^/]+\.test\.[^/]+$/, /(\\__mocks__\\.*)$/];
if (Array.isArray(config.resolver.blockList)) {
config.resolver.blockList = [...config.resolver.blockList, ...testRegexs];
} else if (typeof config.resolver.blockList === 'object') {
config.resolver.blockList = [config.resolver.blockList, ...testRegexs];
}

config.transformer.unstable_allowRequireContext = true;

// due to the nature of this project where it's playing around with packages in and out it's best to reset the cache.
config.resetCache = true;

// @ts-ignore
module.exports = withStorybook(config, {
config = withStorybook(config, {
enabled: true,
configPath: path.resolve(__dirname, './.storybook'),
});

const testRegExps = [/^.*\/[^/]+\.test\.[^/]+$/, /(\\__mocks__\\.*)$/];
/** @type {RegExp[]} */
const blockList = Array.isArray(config.resolver.blockList)
? [...config.resolver.blockList, ...testRegExps]
: [config.resolver.blockList, ...testRegExps];

module.exports = mergeConfig(config, {
watchFolders: [monorepoRoot],
resolver: {
nodeModulesPaths: [
path.resolve(__dirname, 'node_modules'),
path.resolve(monorepoRoot, 'node_modules'),
],
assetExts: [...(config.resolver.assetExts ?? []), 'lottie', 'fbx'],
blockList,
},
transformer: {
unstable_allowRequireContext: true,
},
// due to the nature of this project where it's playing around with packages in and out it's best to reset the cache.
resetCache: true,
});
12 changes: 9 additions & 3 deletions packages/my-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"react-dom": "18.2.0",
"react-hook-form": "^7.53.2",
"react-native": "0.74.5",
"react-native-blob-util": "^0.19.11",
"react-native-file-viewer": "^2.1.5",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.16.2",
Expand All @@ -109,31 +110,36 @@
"react-native-my-empty": "*",
"react-native-my-hooks": "*",
"react-native-my-text": "*",
"react-native-nfc-manager": "^3.16.0",
"react-native-nfc-manager": "^3.16.1",
"react-native-pager-view": "6.3.0",
"react-native-pdf": "^6.7.5",
"react-native-pdf-view": "*",
"react-native-qrcode-svg": "^6.3.12",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"react-native-sticky-parallax-header": "^1.1.1",
"react-native-svg": "15.2.0",
"react-native-try-catch": "*",
"react-native-unistyles": "^2.12.0",
"react-native-web": "~0.19.13",
"react-native-webview": "13.8.6",
"three": "^0.170.0",
"yup": "^1.4.0"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@config-plugins/react-native-blob-util": "^8.0.0",
"@config-plugins/react-native-pdf": "^8.0.0",
"@storybook/addon-ondevice-actions": "^8.4.2",
"@storybook/addon-ondevice-backgrounds": "^8.4.2",
"@storybook/addon-ondevice-controls": "^8.4.2",
"@storybook/addon-ondevice-notes": "^8.4.2",
"@storybook/react": "^8.4.4",
"@storybook/react": "^8.4.5",
"@storybook/react-native": "^8.4.2",
"@testing-library/react-native": "^12.8.1",
"@types/jest": "^29.5.14",
"@types/react": "~18.2.45",
"@types/react": "~18.2.79",
"eslint-config-my": "*",
"jest": "^29.7.0",
"jest-expo": "~51.0.4",
Expand Down
3 changes: 3 additions & 0 deletions packages/my-app/src/__tests__/RootLayout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jest.mock('@/hooks/UserPreferences', () => ({
jest.mock('@/hooks/MyBackgroundFetch', () => ({
WithMyBackgroundFetch: jest.fn((i: any) => i),
}));
jest.mock('@/nfc', () => ({
WithNfc: jest.fn((i: any) => i),
}));
jest.mock('react-native-my-hooks', () => ({
...jest.requireActual('react-native-my-hooks'),
WithNotifications: jest.fn((i: any) => i),
Expand Down
52 changes: 52 additions & 0 deletions packages/my-app/src/app/secure/my-resume-web.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { PdfView, PdfViewPortEventData } from 'react-native-pdf-view';
import { FC, useCallback, useMemo, useState } from 'react';
import { Button, useWindowDimensions, View } from 'react-native';
import samples from '@/data/samplePdfUrls.json';
import { ImageStyle } from 'expo-image';

const ResumeScreen: FC = () => {
const [uri, setUri] = useState(samples[0]);
const windowDimensions = useWindowDimensions();
const [pdfWidth, setPdfWidth] = useState(0);
const [pdfHeight, setPdfHeight] = useState(0);
const viewDimensions = useMemo<ImageStyle>(() => {
if (pdfWidth === 0 || pdfHeight === 0) {
return {
width: windowDimensions.width,
height: 1,
};
} else {
return {
width: windowDimensions.width,
height: (windowDimensions.width / pdfWidth) * pdfHeight,
};
}
}, [windowDimensions.width, pdfWidth, pdfHeight]);
const handleViewPortKnown = useCallback(
({ height, width }: PdfViewPortEventData) => {
setPdfWidth(width);
setPdfHeight(height);
},
[],
);
const flip = useCallback(() => {
const randomUri = samples[Math.floor(Math.random() * samples.length)];
setUri(randomUri);
}, []);

return (
<View>
<PdfView
uri={uri}
onViewPortKnown={handleViewPortKnown}
onError={(error) => {
console.error(error);
}}
style={viewDimensions}
/>
<Button title={uri} onPress={flip} />
</View>
);
};

export default ResumeScreen;
57 changes: 57 additions & 0 deletions packages/my-app/src/app/secure/my-resume.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Pdf from 'react-native-pdf';
import { FC, useCallback, useMemo, useState } from 'react';
import { Button, useWindowDimensions, View, ViewStyle } from 'react-native';
import samples from '@/data/samplePdfUrls.json';

const ResumeScreen: FC = () => {
const [uri, setUri] = useState(samples[0]);
const windowDimensions = useWindowDimensions();
const [pdfWidth, setPdfWidth] = useState(0);
const [pdfHeight, setPdfHeight] = useState(0);
const viewDimensions = useMemo<ViewStyle>(() => {
if (pdfWidth === 0 || pdfHeight === 0) {
return {
width: windowDimensions.width,
height: 1,
};
} else {
return {
width: windowDimensions.width,
height: (windowDimensions.width / pdfWidth) * pdfHeight,
};
}
}, [windowDimensions.width, pdfWidth, pdfHeight]);
const handleViewPortKnown = useCallback(
(
_numberOfPages: number,
_path: string,
size: { height: number; width: number },
) => {
setPdfWidth(size.width);
setPdfHeight(size.height);
},
[],
);
const flip = useCallback(() => {
const randomUri = samples[Math.floor(Math.random() * samples.length)];
setUri(randomUri);
}, []);

return (
<View>
<Pdf
source={{ uri }}
onLoadComplete={handleViewPortKnown}
onError={(error) => {
console.error(error);
}}
style={viewDimensions}
fitPolicy={0}
progressContainerStyle={viewDimensions}
/>
<Button title={uri} onPress={flip} />
</View>
);
};

export default ResumeScreen;
75 changes: 75 additions & 0 deletions packages/my-app/src/app/secure/nfc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Button, ScrollView, StyleSheet, Text } from 'react-native';
import { NfcEvents, NfcTech, TagEvent } from 'react-native-nfc-manager';
import { FC, useCallback, useEffect, useReducer, useState } from 'react';
import { useNfc, WithNfc } from '@/nfc';

export const NfcScreen: FC = () => {
const [scanning, setScanning] = useState(false);
const [tag, setTag] = useState('');
const [discoverBackgroundEvents, pushDiscoverBackgroundEvent] = useReducer(
(prev: TagEvent[], tagEvent: TagEvent) => [...prev, tagEvent],
[],
);
const [discoverEvents, pushDiscoverEvent] = useReducer(
(prev: TagEvent[], tagEvent: TagEvent) => [...prev, tagEvent],
[],
);
const nfc = useNfc();

const scan = useCallback(() => {
setScanning(true);
(async () => {
try {
const nextTag = await nfc.getTagAsync('', NfcTech.Ndef);
setTag(JSON.stringify(nextTag, null, 2));
} catch (e: unknown) {
console.debug('no result', e);
} finally {
setScanning(false);
}
})();
}, [nfc]);

useEffect(() => {
if (nfc.nfcManager) {
nfc.nfcManager.setEventListener(
NfcEvents.DiscoverTag,
(event: TagEvent) => {
pushDiscoverEvent(event);
},
);
nfc.nfcManager.setEventListener(
NfcEvents.DiscoverBackgroundTag,
(event: TagEvent) => {
pushDiscoverBackgroundEvent(event);
},
);
}
return () => {
if (nfc.nfcManager) {
nfc.nfcManager.setEventListener(NfcEvents.DiscoverBackgroundTag, null);
nfc.nfcManager.setEventListener(NfcEvents.DiscoverTag, null);
}
};
}, [nfc]);

return (
<ScrollView contentContainerStyle={styles.wrapper}>
<Button onPress={scan} disabled={scanning} title="Scan a tag" />
<Text>{tag}</Text>
<Text>{JSON.stringify(discoverEvents)}</Text>
<Text>{JSON.stringify(discoverBackgroundEvents)}</Text>
</ScrollView>
);
};

const styles = StyleSheet.create({
wrapper: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
});

export default WithNfc(NfcScreen);
Loading

0 comments on commit a13b276

Please sign in to comment.