UNPKG

@dittolive/ditto

Version:

Ditto is a cross-platform SDK that allows apps to sync with and even without internet connectivity.

142 lines (122 loc) 4.47 kB
import { ConfigPlugin, createRunOncePlugin, withAndroidManifest, withInfoPlist, } from '@expo/config-plugins'; import { withBuildProperties } from 'expo-build-properties'; const BLE_USAGE = 'Uses Bluetooth to connect and sync with nearby devices.'; const LAN_USAGE = 'Uses WiFi to connect and sync with nearby devices.'; type DittoConfig = { /** * The iOS Bluetooth prompt's description. Defaults to "Uses Bluetooth to * connect and sync with nearby devices." */ bluetoothUsageDescription?: string; /** * The iOS LAN prompt's description. Defaults to "Uses WiFi to connect and * sync with nearby devices." */ localNetworkUsageDescription?: string; }; const withDittoIOS: ConfigPlugin<DittoConfig> = (expoConfig, props) => withInfoPlist(expoConfig, (config) => { const infoPlist = config.modResults; infoPlist.NSBluetoothAlwaysUsageDescription = props.bluetoothUsageDescription ?? infoPlist.NSBluetoothAlwaysUsageDescription ?? BLE_USAGE; infoPlist.NSLocalNetworkUsageDescription = props.localNetworkUsageDescription ?? infoPlist.NSLocalNetworkUsageDescription ?? LAN_USAGE; if (!Array.isArray(infoPlist.NSBonjourServices)) { infoPlist.NSBonjourServices = []; } if (!infoPlist.NSBonjourServices.includes('_http-alt._tcp.')) { infoPlist.NSBonjourServices.push('_http-alt._tcp.'); } if (!Array.isArray(infoPlist.UIBackgroundModes)) { infoPlist.UIBackgroundModes = []; } if (!infoPlist.UIBackgroundModes.includes('bluetooth-central')) { infoPlist.UIBackgroundModes.push('bluetooth-central'); } if (!infoPlist.UIBackgroundModes.includes('bluetooth-peripheral')) { infoPlist.UIBackgroundModes.push('bluetooth-peripheral'); } return config; }); const withDittoAndroid: ConfigPlugin<DittoConfig> = (expoConfig) => { const architectures = ['x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a']; const libraries = [ 'libjsi.so', 'libdittoffi.so', 'libreact_nativemodule_core.so', 'libturbomodulejsijni.so', 'libreactnative.so', ]; expoConfig = withBuildProperties(expoConfig, { android: { packagingOptions: { pickFirst: architectures.flatMap((arch) => libraries.map((lib) => `lib/${arch}/${lib}`) ), }, }, }); expoConfig = withAndroidManifest(expoConfig, async (config) => { const androidManifest = config.modResults; const permissions = androidManifest.manifest['uses-permission'] || []; const permissionsToAdd = [ { name: 'android.permission.BLUETOOTH' }, { name: 'android.permission.BLUETOOTH_ADMIN' }, { name: 'android.permission.BLUETOOTH_ADVERTISE' }, { name: 'android.permission.BLUETOOTH_CONNECT' }, { name: 'android.permission.BLUETOOTH_SCAN', attributes: { 'android:usesPermissionFlags': 'neverForLocation' }, }, { name: 'android.permission.ACCESS_FINE_LOCATION' }, { name: 'android.permission.ACCESS_COARSE_LOCATION' }, { name: 'android.permission.INTERNET' }, { name: 'android.permission.ACCESS_WIFI_STATE' }, { name: 'android.permission.ACCESS_NETWORK_STATE' }, { name: 'android.permission.CHANGE_NETWORK_STATE' }, { name: 'android.permission.CHANGE_WIFI_MULTICAST_STATE' }, { name: 'android.permission.CHANGE_WIFI_STATE' }, { name: 'android.permission.NEARBY_WIFI_DEVICES', attributes: { 'android:usesPermissionFlags': 'neverForLocation' }, }, ]; permissionsToAdd.forEach((permission) => { function isPermissionAlreadyRequested( permissionName: string, manifestPermissions: any[] ): boolean { return manifestPermissions.some( (e) => e.$['android:name'] === permissionName ); } if (!isPermissionAlreadyRequested(permission.name, permissions)) { const permissionObject = { $: { 'android:name': permission.name, ...permission.attributes, }, }; permissions.push(permissionObject); } }); androidManifest.manifest['uses-permission'] = permissions; return config; }); return expoConfig; }; const withDitto: ConfigPlugin<DittoConfig> = (config, props = {}) => { config = withDittoIOS(config, props); config = withDittoAndroid(config, props); return config; }; export default createRunOncePlugin(withDitto, 'ditto_expo');