From a8c16e31d660faa54b1258508b01d105a55d00eb Mon Sep 17 00:00:00 2001 From: Erwan LE PRADO <113348625+erwanlpfr@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:54:01 +0100 Subject: [PATCH] feat: Make `enableCodeScanner` expo config-plugin install the native dependency (#2348) * feat: with gradle implementation * chore: remove unused vars * chore: eslint * chore: eslint --- package/src/expo-plugin/@types.ts | 34 +++++++++++++++ .../withAndroidMLKitVisionModel.ts | 25 +++++++++-- package/src/expo-plugin/withVisionCamera.ts | 41 ++----------------- 3 files changed, 59 insertions(+), 41 deletions(-) create mode 100644 package/src/expo-plugin/@types.ts diff --git a/package/src/expo-plugin/@types.ts b/package/src/expo-plugin/@types.ts new file mode 100644 index 0000000..2a57141 --- /dev/null +++ b/package/src/expo-plugin/@types.ts @@ -0,0 +1,34 @@ +export type ConfigProps = { + /** + * The text to show in the native dialog when asking for Camera Permissions. + * @default 'Allow $(PRODUCT_NAME) to access your camera' + */ + cameraPermissionText?: string + /** + * Whether to add Microphone Permissions to the native manifest or not. + * @default false + */ + enableMicrophonePermission?: boolean + /** + * The text to show in the native dialog when asking for Camera Permissions. + * @default 'Allow $(PRODUCT_NAME) to access your microphone' + */ + microphonePermissionText?: string + /** + * Whether to enable the Frame Processors runtime, or explicitly disable it. + * Disabling Frame Processors will make your app smaller as the C++ files will not be compiled. + * See [Frame Processors](https://react-native-vision-camera.com/docs/guides/frame-processors) + * @default false + */ + disableFrameProcessors?: boolean + /** + * Whether to enable the QR/Barcode Scanner Model. If true, the MLKit Model will + * automatically be downloaded on app startup. If false, it will be downloaded + * once the Camera is created with a `CodeScanner`. + * See [QR/Barcode Scanning](https://react-native-vision-camera.com/docs/guides/code-scanning) + * + * If set to true, it fallbacks to `android-manifest`. + * @default false + */ + enableCodeScanner?: boolean | 'android-manifest' | 'gradle-implementation' +} diff --git a/package/src/expo-plugin/withAndroidMLKitVisionModel.ts b/package/src/expo-plugin/withAndroidMLKitVisionModel.ts index 84d1bb5..cfc1828 100644 --- a/package/src/expo-plugin/withAndroidMLKitVisionModel.ts +++ b/package/src/expo-plugin/withAndroidMLKitVisionModel.ts @@ -1,11 +1,30 @@ -import { AndroidConfig, ConfigPlugin, withAndroidManifest } from '@expo/config-plugins' +import { AndroidConfig, ConfigPlugin, withAndroidManifest, withAppBuildGradle } from '@expo/config-plugins' +import { ConfigProps } from './@types' const { addMetaDataItemToMainApplication, getMainApplicationOrThrow } = AndroidConfig.Manifest -export const withAndroidMLKitVisionModel: ConfigPlugin = (config) => { +export const withAndroidMLKitVisionModel: ConfigPlugin = (config, props) => { + if (props.enableCodeScanner === 'gradle-implementation') { + return withAppBuildGradle(config, (conf) => { + const buildGradle = conf.modResults + const implementation = "implementation 'com.google.mlkit:barcode-scanning:17.2.0'" + + if (buildGradle.contents.includes(implementation) === false) { + // Inspired by https://github.com/invertase/react-native-firebase/blob/main/packages/app/plugin/src/android/buildscriptDependency.ts + // TODO: Find a better way to do this + buildGradle.contents = buildGradle.contents.replace( + /dependencies\s?{/, + `dependencies { + ${implementation}`, + ) + } + + return conf + }) + } + return withAndroidManifest(config, (conf) => { const androidManifest = conf.modResults - const mainApplication = getMainApplicationOrThrow(androidManifest) addMetaDataItemToMainApplication(mainApplication, 'com.google.mlkit.vision.DEPENDENCIES', 'barcode') diff --git a/package/src/expo-plugin/withVisionCamera.ts b/package/src/expo-plugin/withVisionCamera.ts index e248980..015b053 100644 --- a/package/src/expo-plugin/withVisionCamera.ts +++ b/package/src/expo-plugin/withVisionCamera.ts @@ -2,46 +2,14 @@ import { withPlugins, AndroidConfig, ConfigPlugin, createRunOncePlugin } from '@ import { withDisableFrameProcessorsAndroid } from './withDisableFrameProcessorsAndroid' import { withDisableFrameProcessorsIOS } from './withDisableFrameProcessorsIOS' import { withAndroidMLKitVisionModel } from './withAndroidMLKitVisionModel' +import { ConfigProps } from './@types' // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment const pkg = require('../../../package.json') const CAMERA_USAGE = 'Allow $(PRODUCT_NAME) to access your camera' const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone' -type Props = { - /** - * The text to show in the native dialog when asking for Camera Permissions. - * @default 'Allow $(PRODUCT_NAME) to access your camera' - */ - cameraPermissionText?: string - /** - * Whether to add Microphone Permissions to the native manifest or not. - * @default false - */ - enableMicrophonePermission?: boolean - /** - * The text to show in the native dialog when asking for Camera Permissions. - * @default 'Allow $(PRODUCT_NAME) to access your microphone' - */ - microphonePermissionText?: string - /** - * Whether to enable the Frame Processors runtime, or explicitly disable it. - * Disabling Frame Processors will make your app smaller as the C++ files will not be compiled. - * See [Frame Processors](https://react-native-vision-camera.com/docs/guides/frame-processors) - * @default false - */ - disableFrameProcessors?: boolean - /** - * Whether to enable the QR/Barcode Scanner Model. If true, the MLKit Model will - * automatically be downloaded on app startup. If false, it will be downloaded - * once the Camera is created with a `CodeScanner`. - * See [QR/Barcode Scanning](https://react-native-vision-camera.com/docs/guides/code-scanning) - * @default false - */ - enableCodeScanner?: boolean -} - -const withCamera: ConfigPlugin = (config, props = {}) => { +const withCamera: ConfigPlugin = (config, props = {}) => { if (config.ios == null) config.ios = {} if (config.ios.infoPlist == null) config.ios.infoPlist = {} config.ios.infoPlist.NSCameraUsageDescription = @@ -58,10 +26,7 @@ const withCamera: ConfigPlugin = (config, props = {}) => { config = withDisableFrameProcessorsIOS(config) } - if (props.enableCodeScanner) { - // Adds meta download-request tag to AndroidManifest - config = withAndroidMLKitVisionModel(config) - } + if (props.enableCodeScanner !== false) config = withAndroidMLKitVisionModel(config, props) return withPlugins(config, [[AndroidConfig.Permissions.withPermissions, androidPermissions]]) }