1import {
2  ConfigPlugin,
3  withPlugins,
4  withAndroidManifest,
5  AndroidConfig,
6  createRunOncePlugin,
7} from 'expo/config-plugins';
8
9const pkg = require('expo-media-library/package.json');
10
11const READ_PHOTOS_USAGE = 'Allow $(PRODUCT_NAME) to access your photos';
12const WRITE_PHOTOS_USAGE = 'Allow $(PRODUCT_NAME) to save photos';
13
14export function modifyAndroidManifest(
15  manifest: AndroidConfig.Manifest.AndroidManifest
16): AndroidConfig.Manifest.AndroidManifest {
17  // Starting with Android 10, the concept of scoped storage is introduced.
18  // Currently, to make expo-media-library working with that change, you have to add
19  // android:requestLegacyExternalStorage="true" to AndroidManifest.xml:
20  const app = AndroidConfig.Manifest.getMainApplicationOrThrow(manifest);
21  app.$['android:requestLegacyExternalStorage'] = 'true';
22  return manifest;
23}
24
25const withMediaLibraryExternalStorage: ConfigPlugin = (config) => {
26  return withAndroidManifest(config, async (config) => {
27    config.modResults = modifyAndroidManifest(config.modResults);
28    return config;
29  });
30};
31
32const withMediaLibrary: ConfigPlugin<
33  {
34    photosPermission?: string;
35    savePhotosPermission?: string;
36    isAccessMediaLocationEnabled?: boolean;
37  } | void
38> = (config, { photosPermission, savePhotosPermission, isAccessMediaLocationEnabled } = {}) => {
39  if (!config.ios) config.ios = {};
40  if (!config.ios.infoPlist) config.ios.infoPlist = {};
41  config.ios.infoPlist.NSPhotoLibraryUsageDescription =
42    photosPermission || config.ios.infoPlist.NSPhotoLibraryUsageDescription || READ_PHOTOS_USAGE;
43  config.ios.infoPlist.NSPhotoLibraryAddUsageDescription =
44    savePhotosPermission ||
45    config.ios.infoPlist.NSPhotoLibraryAddUsageDescription ||
46    WRITE_PHOTOS_USAGE;
47
48  return withPlugins(config, [
49    [
50      AndroidConfig.Permissions.withPermissions,
51      [
52        'android.permission.READ_EXTERNAL_STORAGE',
53        'android.permission.WRITE_EXTERNAL_STORAGE',
54        isAccessMediaLocationEnabled && 'android.permission.ACCESS_MEDIA_LOCATION',
55      ].filter(Boolean),
56    ],
57    withMediaLibraryExternalStorage,
58  ]);
59};
60
61export default createRunOncePlugin(withMediaLibrary, pkg.name, pkg.version);
62