Skip to content

Commit 7e5e874

Browse files
authored
feat: make react-native-share and react-native-haptic-feedback optional (#1744)
1 parent 5ff90fa commit 7e5e874

File tree

20 files changed

+570
-310
lines changed

20 files changed

+570
-310
lines changed

docusaurus/docs/reactnative/basics/getting_started.mdx

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ Most if not all of the required packages now support auto-linking so setup shoul
7070
<TabItem value='yarn'>
7171

7272
```bash
73-
yarn add @react-native-camera-roll/camera-roll @react-native-community/netinfo @stream-io/flat-list-mvcp react-native-document-picker react-native-fs react-native-gesture-handler react-native-haptic-feedback react-native-haptic-feedback react-native-image-crop-picker react-native-image-resizer react-native-reanimated react-native-share react-native-svg
73+
yarn add @react-native-camera-roll/camera-roll @react-native-community/netinfo @stream-io/flat-list-mvcp react-native-document-picker react-native-fs react-native-gesture-handler react-native-image-crop-picker react-native-image-resizer react-native-reanimated react-native-svg
7474
```
7575

7676
</TabItem>
7777
<TabItem value='npm'>
7878

7979
```bash
80-
npm install @react-native-camera-roll/camera-roll @react-native-community/netinfo @stream-io/flat-list-mvcp react-native-document-picker react-native-fs react-native-gesture-handler react-native-haptic-feedback react-native-haptic-feedback react-native-image-crop-picker react-native-image-resizer react-native-reanimated react-native-share react-native-svg
80+
npm install @react-native-camera-roll/camera-roll @react-native-community/netinfo @stream-io/flat-list-mvcp react-native-document-picker react-native-fs react-native-gesture-handler react-native-image-crop-picker react-native-image-resizer react-native-reanimated react-native-svg
8181
```
8282

8383
</TabItem>
@@ -199,6 +199,64 @@ include ':react-native-video'
199199
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android-exoplayer')
200200
```
201201

202+
#### Sharing attachments
203+
204+
Install `react-native-share` in your React Native project.
205+
206+
Installing this package will allow your users to share attachments from the gallery using the native sharing interface on their devices.
207+
208+
<Tabs
209+
defaultValue='yarn'
210+
values={[
211+
{ label: 'Yarn', value: 'yarn' },
212+
{ label: 'npm', value: 'npm' },
213+
]}
214+
>
215+
<TabItem value='yarn'>
216+
217+
```bash
218+
yarn add react-native-share
219+
```
220+
221+
</TabItem>
222+
<TabItem value='npm'>
223+
224+
```bash
225+
npm install react-native-share
226+
```
227+
228+
</TabItem>
229+
</Tabs>
230+
231+
#### Haptic feedback
232+
233+
Install `react-native-haptic-feedback` in your React Native project.
234+
235+
Installing this package will enable haptic feedback when scaling images in the image gallery if the scaling hits the higher or lower limits for its value.
236+
237+
<Tabs
238+
defaultValue='yarn'
239+
values={[
240+
{ label: 'Yarn', value: 'yarn' },
241+
{ label: 'npm', value: 'npm' },
242+
]}
243+
>
244+
<TabItem value='yarn'>
245+
246+
```bash
247+
yarn add react-native-haptic-feedback
248+
```
249+
250+
</TabItem>
251+
<TabItem value='npm'>
252+
253+
```bash
254+
npm install react-native-haptic-feedback
255+
```
256+
257+
</TabItem>
258+
</Tabs>
259+
202260
### AndroidX Support
203261

204262
> AndroidX is a major step forward in the Android ecosystem, and the old support library artifacts are being deprecated.

package/native-package/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,12 @@
2828
"scripts": {
2929
"prepack": " cp ../../README.md .",
3030
"postpack": "rm README.md"
31+
},
32+
"devDependencies": {
33+
"@react-native-camera-roll/camera-roll": "^5.0.2",
34+
"@types/react-native-share": "^3.3.3",
35+
"react-native-document-picker": "^8.1.1",
36+
"react-native-haptic-feedback": "^1.14.0",
37+
"react-native-image-crop-picker": "^0.38.0"
3138
}
3239
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { default as OriginalNetInfo, NetInfoState } from '@react-native-community/netinfo';
2+
3+
export const NetInfo = {
4+
addEventListener(listener) {
5+
let unsubscribe;
6+
// For NetInfo >= 3.x.x
7+
if (OriginalNetInfo.fetch && typeof OriginalNetInfo.fetch === 'function') {
8+
unsubscribe = OriginalNetInfo.addEventListener(({ isConnected, isInternetReachable }) => {
9+
// Initialize with truthy value when internetReachable is still loading
10+
// if it resolves to false, listener is triggered with false value and network
11+
// status is updated
12+
listener(isInternetReachable === null ? isConnected : isConnected && isInternetReachable);
13+
});
14+
return unsubscribe;
15+
} else {
16+
// For NetInfo < 3.x.x
17+
unsubscribe = OriginalNetInfo.addEventListener('connectionChange', () => {
18+
// @ts-ignore
19+
OriginalNetInfo.isConnected.fetch().then((isConnected: NetInfoState) => {
20+
listener(isConnected);
21+
});
22+
});
23+
24+
return unsubscribe.remove;
25+
}
26+
},
27+
fetch() {
28+
return new Promise((resolve, reject) => {
29+
// For NetInfo >= 3.x.x
30+
if (OriginalNetInfo.fetch && typeof OriginalNetInfo.fetch === 'function') {
31+
OriginalNetInfo.fetch().then(({ isConnected }) => {
32+
resolve(isConnected);
33+
}, reject);
34+
} else {
35+
// For NetInfo < 3.x.x
36+
// @ts-ignore
37+
OriginalNetInfo.isConnected.fetch().then((isConnected: NetInfoState) => {
38+
resolve(isConnected);
39+
}, reject);
40+
}
41+
});
42+
},
43+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import AudioVideoPlayer from '../optionalDependencies/Video';
2+
3+
export const Sound = {
4+
initializeSound: null,
5+
// eslint-disable-next-line react/display-name
6+
Player: AudioVideoPlayer
7+
? ({ onBuffer, onEnd, onLoad, onProgress, paused, soundRef, style, uri }) => (
8+
<AudioVideoPlayer
9+
audioOnly={true}
10+
onBuffer={onBuffer}
11+
onEnd={onEnd}
12+
onError={(error: Error) => {
13+
console.log(error);
14+
}}
15+
onLoad={onLoad}
16+
onProgress={onProgress}
17+
paused={paused}
18+
ref={soundRef}
19+
source={{
20+
uri,
21+
}}
22+
style={style}
23+
/>
24+
)
25+
: null,
26+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import AudioVideoPlayer from '../optionalDependencies/Video';
2+
export const Video = AudioVideoPlayer
3+
? ({ onBuffer, onEnd, onLoad, onProgress, paused, repeat, style, uri, videoRef }) => (
4+
<AudioVideoPlayer
5+
ignoreSilentSwitch={'ignore'}
6+
onBuffer={onBuffer}
7+
onEnd={onEnd}
8+
onError={(error) => {
9+
console.error(error);
10+
}}
11+
onLoad={onLoad}
12+
onProgress={onProgress}
13+
paused={paused}
14+
ref={videoRef}
15+
repeat={repeat}
16+
source={{
17+
uri,
18+
}}
19+
style={style}
20+
/>
21+
)
22+
: null;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// @ts-ignore this module does not have a type declaration
2+
import ImageResizer from 'react-native-image-resizer';
3+
4+
type CompressImageParams = {
5+
compressImageQuality: number;
6+
height: number;
7+
uri: string;
8+
width: number;
9+
};
10+
11+
export const compressImage = async ({
12+
compressImageQuality = 1,
13+
height,
14+
uri,
15+
width,
16+
}: CompressImageParams) => {
17+
try {
18+
const { uri: compressedUri } = await ImageResizer.createResizedImage(
19+
uri,
20+
height,
21+
width,
22+
'JPEG',
23+
Math.min(Math.max(0, compressImageQuality), 1) * 100,
24+
0,
25+
undefined,
26+
false,
27+
'cover',
28+
);
29+
return compressedUri;
30+
} catch (error) {
31+
console.log(error);
32+
return uri;
33+
}
34+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import RNFS from 'react-native-fs';
2+
3+
export const deleteFile = async ({ uri }: { uri: string }) => {
4+
try {
5+
await RNFS.unlink(uri);
6+
return true;
7+
} catch (error) {
8+
console.log('File deletion failed...');
9+
return false;
10+
}
11+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { CameraRoll } from '@react-native-camera-roll/camera-roll';
2+
3+
export const getLocalAssetUri = async (remoteUri: string) => {
4+
try {
5+
const localUri = await CameraRoll.save(remoteUri);
6+
return localUri;
7+
} catch {
8+
throw new Error('getLocalAssetUri Error');
9+
}
10+
};
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { PermissionsAndroid, Platform } from 'react-native';
2+
import { CameraRoll, GetPhotosParams } from '@react-native-camera-roll/camera-roll';
3+
4+
export const getPhotos = async ({ after, first }: Pick<GetPhotosParams, 'after' | 'first'>) => {
5+
try {
6+
if (Platform.OS === 'android') {
7+
const readExternalStoragePermissionAndroid =
8+
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE;
9+
const hasPermission = await PermissionsAndroid.check(readExternalStoragePermissionAndroid);
10+
if (!hasPermission) {
11+
const granted = await PermissionsAndroid.request(readExternalStoragePermissionAndroid, {
12+
buttonNegative: 'Deny',
13+
buttonNeutral: 'Ask Me Later',
14+
buttonPositive: 'Allow',
15+
message: 'Permissions are required to access and share photos.',
16+
title: 'Photos Access',
17+
});
18+
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
19+
throw new Error('getPhotos Error');
20+
}
21+
}
22+
}
23+
const results = await CameraRoll.getPhotos({
24+
after,
25+
assetType: 'All',
26+
first,
27+
include: ['fileSize', 'filename', 'imageSize', 'playableDuration'],
28+
});
29+
const assets = results.edges.map((edge) => ({
30+
...edge.node.image,
31+
source: 'picker',
32+
}));
33+
const hasNextPage = results.page_info.has_next_page;
34+
const endCursor = results.page_info.end_cursor;
35+
return { assets, endCursor, hasNextPage };
36+
} catch (_error) {
37+
throw new Error('getPhotos Error');
38+
}
39+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export * from './shareImage';
2+
export * from './deleteFile';
3+
export * from './compressImage';
4+
export * from './getLocalAssetUri';
5+
export * from './getPhotos';
6+
export * from './NetInfo';
7+
export * from './saveFile';
8+
export * from './takePhoto';
9+
export * from './triggerHaptic';
10+
export * from './Sound';
11+
export * from './Video';

0 commit comments

Comments
 (0)