1082815dcSEvan Bacon"use strict";
2082815dcSEvan Bacon
3082815dcSEvan BaconObject.defineProperty(exports, "__esModule", {
4082815dcSEvan Bacon  value: true
5082815dcSEvan Bacon});
6082815dcSEvan Baconexports.appendScheme = appendScheme;
7082815dcSEvan Baconexports.ensureManifestHasValidIntentFilter = ensureManifestHasValidIntentFilter;
8082815dcSEvan Baconexports.getScheme = getScheme;
9082815dcSEvan Baconexports.getSchemesFromManifest = getSchemesFromManifest;
10082815dcSEvan Baconexports.hasScheme = hasScheme;
11082815dcSEvan Baconexports.removeScheme = removeScheme;
12082815dcSEvan Baconexports.setScheme = setScheme;
13082815dcSEvan Baconexports.withScheme = void 0;
14082815dcSEvan Baconfunction _androidPlugins() {
15082815dcSEvan Bacon  const data = require("../plugins/android-plugins");
16082815dcSEvan Bacon  _androidPlugins = function () {
17082815dcSEvan Bacon    return data;
18082815dcSEvan Bacon  };
19082815dcSEvan Bacon  return data;
20082815dcSEvan Bacon}
21082815dcSEvan Baconfunction _warnings() {
22082815dcSEvan Bacon  const data = require("../utils/warnings");
23082815dcSEvan Bacon  _warnings = function () {
24082815dcSEvan Bacon    return data;
25082815dcSEvan Bacon  };
26082815dcSEvan Bacon  return data;
27082815dcSEvan Bacon}
28082815dcSEvan Baconconst withScheme = (0, _androidPlugins().createAndroidManifestPlugin)(setScheme, 'withScheme');
29082815dcSEvan Baconexports.withScheme = withScheme;
30082815dcSEvan Baconfunction getScheme(config) {
31082815dcSEvan Bacon  if (Array.isArray(config.scheme)) {
32082815dcSEvan Bacon    const validate = value => typeof value === 'string';
33082815dcSEvan Bacon    return config.scheme.filter(validate);
34082815dcSEvan Bacon  } else if (typeof config.scheme === 'string') {
35082815dcSEvan Bacon    return [config.scheme];
36082815dcSEvan Bacon  }
37082815dcSEvan Bacon  return [];
38ee216927STomasz Sapeta}
39ee216927STomasz Sapeta
40ee216927STomasz Sapeta// This plugin used to remove the unused schemes but this is unpredictable because other plugins could add schemes.
41*384598e2SBrent Vatne// The only way to reliably remove schemes from the project is to nuke the file and regenerate the code (`npx expo prebuild --clean`).
42082815dcSEvan Bacon// Regardless, having extra schemes isn't a fatal issue and therefore a tolerable compromise is to just add new schemes that aren't currently present.
43082815dcSEvan Baconfunction setScheme(config, androidManifest) {
44082815dcSEvan Bacon  var _config$android, _config$android2;
45ee216927STomasz Sapeta  const schemes = [...getScheme(config),
46ee216927STomasz Sapeta  // @ts-ignore: TODO: android.scheme is an unreleased -- harder to add to turtle v1.
47ee216927STomasz Sapeta  ...getScheme((_config$android = config.android) !== null && _config$android !== void 0 ? _config$android : {})];
48ee216927STomasz Sapeta  // Add the package name to the list of schemes for easier Google auth and parity with Turtle v1.
49082815dcSEvan Bacon  if ((_config$android2 = config.android) !== null && _config$android2 !== void 0 && _config$android2.package) {
50082815dcSEvan Bacon    schemes.push(config.android.package);
51082815dcSEvan Bacon  }
52082815dcSEvan Bacon  if (schemes.length === 0) {
53082815dcSEvan Bacon    return androidManifest;
54082815dcSEvan Bacon  }
55082815dcSEvan Bacon  if (!ensureManifestHasValidIntentFilter(androidManifest)) {
56082815dcSEvan Bacon    (0, _warnings().addWarningAndroid)('scheme', `Cannot add schemes because the provided manifest does not have a valid Activity with \`android:launchMode="singleTask"\``, 'https://expo.fyi/setup-android-uri-scheme');
57082815dcSEvan Bacon    return androidManifest;
58ee216927STomasz Sapeta  }
59082815dcSEvan Bacon
60ee216927STomasz Sapeta  // Get the current schemes and remove them from the list of schemes to add.
61082815dcSEvan Bacon  const currentSchemes = getSchemesFromManifest(androidManifest);
62082815dcSEvan Bacon  for (const uri of currentSchemes) {
63082815dcSEvan Bacon    const index = schemes.indexOf(uri);
64082815dcSEvan Bacon    if (index > -1) schemes.splice(index, 1);
65ee216927STomasz Sapeta  }
66082815dcSEvan Bacon
67ee216927STomasz Sapeta  // Now add all of the remaining schemes.
68082815dcSEvan Bacon  for (const uri of schemes) {
69082815dcSEvan Bacon    androidManifest = appendScheme(uri, androidManifest);
70082815dcSEvan Bacon  }
71082815dcSEvan Bacon  return androidManifest;
72082815dcSEvan Bacon}
73082815dcSEvan Baconfunction isValidRedirectIntentFilter({
74082815dcSEvan Bacon  actions,
75082815dcSEvan Bacon  categories
76082815dcSEvan Bacon}) {
77082815dcSEvan Bacon  return actions.includes('android.intent.action.VIEW') && !categories.includes('android.intent.category.LAUNCHER');
78082815dcSEvan Bacon}
79082815dcSEvan Baconfunction propertiesFromIntentFilter(intentFilter) {
80082815dcSEvan Bacon  var _intentFilter$action$, _intentFilter$action, _intentFilter$categor, _intentFilter$categor2, _intentFilter$data$fi, _intentFilter$data, _intentFilter$data$fi2;
81082815dcSEvan Bacon  const actions = (_intentFilter$action$ = intentFilter === null || intentFilter === void 0 ? void 0 : (_intentFilter$action = intentFilter.action) === null || _intentFilter$action === void 0 ? void 0 : _intentFilter$action.map(data => {
82082815dcSEvan Bacon    var _data$$;
83082815dcSEvan Bacon    return data === null || data === void 0 ? void 0 : (_data$$ = data.$) === null || _data$$ === void 0 ? void 0 : _data$$['android:name'];
84082815dcSEvan Bacon  })) !== null && _intentFilter$action$ !== void 0 ? _intentFilter$action$ : [];
85082815dcSEvan Bacon  const categories = (_intentFilter$categor = intentFilter === null || intentFilter === void 0 ? void 0 : (_intentFilter$categor2 = intentFilter.category) === null || _intentFilter$categor2 === void 0 ? void 0 : _intentFilter$categor2.map(data => {
86082815dcSEvan Bacon    var _data$$2;
87082815dcSEvan Bacon    return data === null || data === void 0 ? void 0 : (_data$$2 = data.$) === null || _data$$2 === void 0 ? void 0 : _data$$2['android:name'];
88082815dcSEvan Bacon  })) !== null && _intentFilter$categor !== void 0 ? _intentFilter$categor : [];
89082815dcSEvan Bacon  const data = (_intentFilter$data$fi = intentFilter === null || intentFilter === void 0 ? void 0 : (_intentFilter$data = intentFilter.data) === null || _intentFilter$data === void 0 ? void 0 : (_intentFilter$data$fi2 = _intentFilter$data.filter(data => {
90082815dcSEvan Bacon    var _data$$3;
91082815dcSEvan Bacon    return data === null || data === void 0 ? void 0 : (_data$$3 = data.$) === null || _data$$3 === void 0 ? void 0 : _data$$3['android:scheme'];
92082815dcSEvan Bacon  })) === null || _intentFilter$data$fi2 === void 0 ? void 0 : _intentFilter$data$fi2.map(data => {
93082815dcSEvan Bacon    var _data$$4, _data$$5;
94082815dcSEvan Bacon    return {
95082815dcSEvan Bacon      scheme: data === null || data === void 0 ? void 0 : (_data$$4 = data.$) === null || _data$$4 === void 0 ? void 0 : _data$$4['android:scheme'],
96082815dcSEvan Bacon      host: data === null || data === void 0 ? void 0 : (_data$$5 = data.$) === null || _data$$5 === void 0 ? void 0 : _data$$5['android:host']
97082815dcSEvan Bacon    };
98082815dcSEvan Bacon  })) !== null && _intentFilter$data$fi !== void 0 ? _intentFilter$data$fi : [];
99082815dcSEvan Bacon  return {
100082815dcSEvan Bacon    actions,
101082815dcSEvan Bacon    categories,
102082815dcSEvan Bacon    data
103082815dcSEvan Bacon  };
104082815dcSEvan Bacon}
105082815dcSEvan Baconfunction getSingleTaskIntentFilters(androidManifest) {
106082815dcSEvan Bacon  if (!Array.isArray(androidManifest.manifest.application)) return [];
107082815dcSEvan Bacon  let outputSchemes = [];
108082815dcSEvan Bacon  for (const application of androidManifest.manifest.application) {
109082815dcSEvan Bacon    const {
110082815dcSEvan Bacon      activity
111ee216927STomasz Sapeta    } = application;
112ee216927STomasz Sapeta    // @ts-ignore
113082815dcSEvan Bacon    const activities = Array.isArray(activity) ? activity : [activity];
114082815dcSEvan Bacon    const singleTaskActivities = activities.filter(activity => {
115082815dcSEvan Bacon      var _activity$$;
116082815dcSEvan Bacon      return (activity === null || activity === void 0 ? void 0 : (_activity$$ = activity.$) === null || _activity$$ === void 0 ? void 0 : _activity$$['android:launchMode']) === 'singleTask';
117082815dcSEvan Bacon    });
118082815dcSEvan Bacon    for (const activity of singleTaskActivities) {
119082815dcSEvan Bacon      const intentFilters = activity['intent-filter'];
120082815dcSEvan Bacon      outputSchemes = outputSchemes.concat(intentFilters);
121082815dcSEvan Bacon    }
122082815dcSEvan Bacon  }
123082815dcSEvan Bacon  return outputSchemes;
124082815dcSEvan Bacon}
125082815dcSEvan Baconfunction getSchemesFromManifest(androidManifest, requestedHost = null) {
126082815dcSEvan Bacon  const outputSchemes = [];
127082815dcSEvan Bacon  const singleTaskIntentFilters = getSingleTaskIntentFilters(androidManifest);
128082815dcSEvan Bacon  for (const intentFilter of singleTaskIntentFilters) {
129082815dcSEvan Bacon    const properties = propertiesFromIntentFilter(intentFilter);
130082815dcSEvan Bacon    if (isValidRedirectIntentFilter(properties) && properties.data) {
131082815dcSEvan Bacon      for (const {
132082815dcSEvan Bacon        scheme,
133082815dcSEvan Bacon        host
134082815dcSEvan Bacon      } of properties.data) {
135082815dcSEvan Bacon        if (requestedHost === null || !host || host === requestedHost) {
136082815dcSEvan Bacon          outputSchemes.push(scheme);
137082815dcSEvan Bacon        }
138082815dcSEvan Bacon      }
139082815dcSEvan Bacon    }
140082815dcSEvan Bacon  }
141082815dcSEvan Bacon  return outputSchemes;
142082815dcSEvan Bacon}
143082815dcSEvan Baconfunction ensureManifestHasValidIntentFilter(androidManifest) {
144082815dcSEvan Bacon  if (!Array.isArray(androidManifest.manifest.application)) {
145082815dcSEvan Bacon    return false;
146082815dcSEvan Bacon  }
147082815dcSEvan Bacon  for (const application of androidManifest.manifest.application) {
148082815dcSEvan Bacon    for (const activity of application.activity || []) {
149082815dcSEvan Bacon      var _activity$$2;
150082815dcSEvan Bacon      if ((activity === null || activity === void 0 ? void 0 : (_activity$$2 = activity.$) === null || _activity$$2 === void 0 ? void 0 : _activity$$2['android:launchMode']) === 'singleTask') {
151082815dcSEvan Bacon        for (const intentFilter of activity['intent-filter'] || []) {
152082815dcSEvan Bacon          // Parse valid intent filters...
153082815dcSEvan Bacon          const properties = propertiesFromIntentFilter(intentFilter);
154082815dcSEvan Bacon          if (isValidRedirectIntentFilter(properties)) {
155082815dcSEvan Bacon            return true;
156082815dcSEvan Bacon          }
157082815dcSEvan Bacon        }
158082815dcSEvan Bacon        if (!activity['intent-filter']) {
159082815dcSEvan Bacon          activity['intent-filter'] = [];
160082815dcSEvan Bacon        }
161082815dcSEvan Bacon        activity['intent-filter'].push({
162082815dcSEvan Bacon          action: [{
163082815dcSEvan Bacon            $: {
164082815dcSEvan Bacon              'android:name': 'android.intent.action.VIEW'
165082815dcSEvan Bacon            }
166082815dcSEvan Bacon          }],
167082815dcSEvan Bacon          category: [{
168082815dcSEvan Bacon            $: {
169082815dcSEvan Bacon              'android:name': 'android.intent.category.DEFAULT'
170082815dcSEvan Bacon            }
171082815dcSEvan Bacon          }, {
172082815dcSEvan Bacon            $: {
173082815dcSEvan Bacon              'android:name': 'android.intent.category.BROWSABLE'
174082815dcSEvan Bacon            }
175082815dcSEvan Bacon          }]
176082815dcSEvan Bacon        });
177082815dcSEvan Bacon        return true;
178082815dcSEvan Bacon      }
179082815dcSEvan Bacon    }
180082815dcSEvan Bacon  }
181082815dcSEvan Bacon  return false;
182082815dcSEvan Bacon}
183082815dcSEvan Baconfunction hasScheme(scheme, androidManifest) {
184082815dcSEvan Bacon  const schemes = getSchemesFromManifest(androidManifest);
185082815dcSEvan Bacon  return schemes.includes(scheme);
186082815dcSEvan Bacon}
187082815dcSEvan Baconfunction appendScheme(scheme, androidManifest) {
188082815dcSEvan Bacon  if (!Array.isArray(androidManifest.manifest.application)) {
189082815dcSEvan Bacon    return androidManifest;
190082815dcSEvan Bacon  }
191082815dcSEvan Bacon  for (const application of androidManifest.manifest.application) {
192082815dcSEvan Bacon    for (const activity of application.activity || []) {
193082815dcSEvan Bacon      var _activity$$3;
194082815dcSEvan Bacon      if ((activity === null || activity === void 0 ? void 0 : (_activity$$3 = activity.$) === null || _activity$$3 === void 0 ? void 0 : _activity$$3['android:launchMode']) === 'singleTask') {
195082815dcSEvan Bacon        for (const intentFilter of activity['intent-filter'] || []) {
196082815dcSEvan Bacon          const properties = propertiesFromIntentFilter(intentFilter);
197082815dcSEvan Bacon          if (isValidRedirectIntentFilter(properties)) {
198082815dcSEvan Bacon            if (!intentFilter.data) intentFilter.data = [];
199082815dcSEvan Bacon            intentFilter.data.push({
200082815dcSEvan Bacon              $: {
201082815dcSEvan Bacon                'android:scheme': scheme
202082815dcSEvan Bacon              }
203082815dcSEvan Bacon            });
204082815dcSEvan Bacon          }
205082815dcSEvan Bacon        }
206082815dcSEvan Bacon        break;
207082815dcSEvan Bacon      }
208082815dcSEvan Bacon    }
209082815dcSEvan Bacon  }
210082815dcSEvan Bacon  return androidManifest;
211082815dcSEvan Bacon}
212082815dcSEvan Baconfunction removeScheme(scheme, androidManifest) {
213082815dcSEvan Bacon  if (!Array.isArray(androidManifest.manifest.application)) {
214082815dcSEvan Bacon    return androidManifest;
215082815dcSEvan Bacon  }
216082815dcSEvan Bacon  for (const application of androidManifest.manifest.application) {
217082815dcSEvan Bacon    for (const activity of application.activity || []) {
218082815dcSEvan Bacon      var _activity$$4;
219082815dcSEvan Bacon      if ((activity === null || activity === void 0 ? void 0 : (_activity$$4 = activity.$) === null || _activity$$4 === void 0 ? void 0 : _activity$$4['android:launchMode']) === 'singleTask') {
220082815dcSEvan Bacon        for (const intentFilter of activity['intent-filter'] || []) {
221082815dcSEvan Bacon          // Parse valid intent filters...
222082815dcSEvan Bacon          const properties = propertiesFromIntentFilter(intentFilter);
223082815dcSEvan Bacon          if (isValidRedirectIntentFilter(properties)) {
224082815dcSEvan Bacon            for (const dataKey in (intentFilter === null || intentFilter === void 0 ? void 0 : intentFilter.data) || []) {
225082815dcSEvan Bacon              var _intentFilter$data2, _data$$6;
226082815dcSEvan Bacon              const data = (_intentFilter$data2 = intentFilter.data) === null || _intentFilter$data2 === void 0 ? void 0 : _intentFilter$data2[dataKey];
227082815dcSEvan Bacon              if ((data === null || data === void 0 ? void 0 : (_data$$6 = data.$) === null || _data$$6 === void 0 ? void 0 : _data$$6['android:scheme']) === scheme) {
228082815dcSEvan Bacon                var _intentFilter$data3;
229082815dcSEvan Bacon                (_intentFilter$data3 = intentFilter.data) === null || _intentFilter$data3 === void 0 ? true : delete _intentFilter$data3[dataKey];
230082815dcSEvan Bacon              }
231082815dcSEvan Bacon            }
232082815dcSEvan Bacon          }
233082815dcSEvan Bacon        }
234082815dcSEvan Bacon        break;
235082815dcSEvan Bacon      }
236082815dcSEvan Bacon    }
237082815dcSEvan Bacon  }
238082815dcSEvan Bacon  return androidManifest;
239082815dcSEvan Bacon}
240082815dcSEvan Bacon//# sourceMappingURL=Scheme.js.map