Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pdf and Nfc #18

Merged
merged 36 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2a0676f
chore: specify schema
trajano Nov 11, 2024
7f0a712
feat: pdfview as a WebView
trajano Nov 12, 2024
73627ca
feat: render the PDF to an image
trajano Nov 13, 2024
920df98
fix: removed merge conflicts
trajano Nov 15, 2024
60f0ebd
chore: remove pdfjs-dist
trajano Nov 14, 2024
d32d8d8
feat: nfc
trajano Nov 18, 2024
9d0b65d
feat: added react native unistyles
trajano Nov 18, 2024
459b58f
refactor: updated parameters to keep parity with image
trajano Nov 18, 2024
c04316d
feat: added page count
trajano Nov 18, 2024
cf7e058
refactor: use metro-config mergeConfig
trajano Nov 18, 2024
9322377
feat: additional stories from doc examples
trajano Nov 18, 2024
c8afed8
feat: keyboard story
trajano Nov 18, 2024
96639b0
feat: added Switch to Keyboard story
trajano Nov 18, 2024
092fb87
feat: added Activity Indicator to Keyboard story
trajano Nov 18, 2024
78b5b01
feat: nfc test page
trajano Nov 18, 2024
3b6fcee
refactor: move WebView to PdfWebView
trajano Nov 19, 2024
5fa9f31
feat: added react-native-pdf
trajano Nov 19, 2024
846d784
docs: note about expo-module-scripts
trajano Nov 19, 2024
875df1d
feat: use react-native-pdf
trajano Nov 19, 2024
70e410b
chore(deps): updated deps
trajano Nov 19, 2024
5c5b6c0
chore(deps): updated deps
trajano Nov 20, 2024
15a56fc
fix: does not auto zoom anytmore and defaults to my resume since it i…
trajano Nov 21, 2024
3d7ae38
chore(deps): updated deps
trajano Nov 21, 2024
4686706
chore: remove the HTML experiments with pdf js
trajano Nov 21, 2024
28b3eda
chore: remove console.logs
trajano Nov 21, 2024
e3021fc
test: reactivate the tests but disable assertions
trajano Nov 21, 2024
a00b0db
chore: lint fix
trajano Nov 21, 2024
f5a3988
chore: lint fix
trajano Nov 21, 2024
21bed49
chore: lint fix
trajano Nov 21, 2024
dd02458
chore: removed unused code
trajano Nov 21, 2024
5750f66
chore: removed unused code
trajano Nov 21, 2024
4593f3c
feat: re-add PdfView sample
trajano Nov 21, 2024
c0d98bb
test: increase timeout
trajano Nov 21, 2024
779808e
test: increase timeout
trajano Nov 21, 2024
44c0de6
refactor: pdf urls
trajano Nov 21, 2024
1ca5211
test: coverage
trajano Nov 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading