1import { ExpoConfig } from '@expo/config-types';
2
3import { ConfigPlugin, Mod } from '../Plugin.types';
4import { Manifest, Paths, Properties, Resources } from '../android';
5import { withMod } from './withMod';
6
7type OptionalPromise<T> = T | Promise<T>;
8
9type MutateDataAction<T> = (expo: ExpoConfig, data: T) => OptionalPromise<T>;
10
11/**
12 * Helper method for creating mods from existing config functions.
13 *
14 * @param action
15 */
16export function createAndroidManifestPlugin(
17  action: MutateDataAction<Manifest.AndroidManifest>,
18  name: string
19): ConfigPlugin {
20  const withUnknown: ConfigPlugin = (config) =>
21    withAndroidManifest(config, async (config) => {
22      config.modResults = await action(config, config.modResults);
23      return config;
24    });
25  if (name) {
26    Object.defineProperty(withUnknown, 'name', {
27      value: name,
28    });
29  }
30  return withUnknown;
31}
32
33export function createStringsXmlPlugin(
34  action: MutateDataAction<Resources.ResourceXML>,
35  name: string
36): ConfigPlugin {
37  const withUnknown: ConfigPlugin = (config) =>
38    withStringsXml(config, async (config) => {
39      config.modResults = await action(config, config.modResults);
40      return config;
41    });
42  if (name) {
43    Object.defineProperty(withUnknown, 'name', {
44      value: name,
45    });
46  }
47  return withUnknown;
48}
49
50/**
51 * Provides the AndroidManifest.xml for modification.
52 *
53 * @param config
54 * @param action
55 */
56export const withAndroidManifest: ConfigPlugin<Mod<Manifest.AndroidManifest>> = (
57  config,
58  action
59) => {
60  return withMod(config, {
61    platform: 'android',
62    mod: 'manifest',
63    action,
64  });
65};
66
67/**
68 * Provides the strings.xml for modification.
69 *
70 * @param config
71 * @param action
72 */
73export const withStringsXml: ConfigPlugin<Mod<Resources.ResourceXML>> = (config, action) => {
74  return withMod(config, {
75    platform: 'android',
76    mod: 'strings',
77    action,
78  });
79};
80
81/**
82 * Provides the `android/app/src/main/res/values/colors.xml` as JSON (parsed with [`xml2js`](https://www.npmjs.com/package/xml2js)).
83 *
84 * @param config
85 * @param action
86 */
87export const withAndroidColors: ConfigPlugin<Mod<Resources.ResourceXML>> = (config, action) => {
88  return withMod(config, {
89    platform: 'android',
90    mod: 'colors',
91    action,
92  });
93};
94
95/**
96 * Provides the `android/app/src/main/res/values-night/colors.xml` as JSON (parsed with [`xml2js`](https://www.npmjs.com/package/xml2js)).
97 *
98 * @param config
99 * @param action
100 */
101export const withAndroidColorsNight: ConfigPlugin<Mod<Resources.ResourceXML>> = (
102  config,
103  action
104) => {
105  return withMod(config, {
106    platform: 'android',
107    mod: 'colorsNight',
108    action,
109  });
110};
111
112/**
113 * Provides the `android/app/src/main/res/values/styles.xml` as JSON (parsed with [`xml2js`](https://www.npmjs.com/package/xml2js)).
114 *
115 * @param config
116 * @param action
117 */
118export const withAndroidStyles: ConfigPlugin<Mod<Resources.ResourceXML>> = (config, action) => {
119  return withMod(config, {
120    platform: 'android',
121    mod: 'styles',
122    action,
123  });
124};
125
126/**
127 * Provides the project MainActivity for modification.
128 *
129 * @param config
130 * @param action
131 */
132export const withMainActivity: ConfigPlugin<Mod<Paths.ApplicationProjectFile>> = (
133  config,
134  action
135) => {
136  return withMod(config, {
137    platform: 'android',
138    mod: 'mainActivity',
139    action,
140  });
141};
142
143/**
144 * Provides the project MainApplication for modification.
145 *
146 * @param config
147 * @param action
148 */
149export const withMainApplication: ConfigPlugin<Mod<Paths.ApplicationProjectFile>> = (
150  config,
151  action
152) => {
153  return withMod(config, {
154    platform: 'android',
155    mod: 'mainApplication',
156    action,
157  });
158};
159
160/**
161 * Provides the project /build.gradle for modification.
162 *
163 * @param config
164 * @param action
165 */
166export const withProjectBuildGradle: ConfigPlugin<Mod<Paths.GradleProjectFile>> = (
167  config,
168  action
169) => {
170  return withMod(config, {
171    platform: 'android',
172    mod: 'projectBuildGradle',
173    action,
174  });
175};
176
177/**
178 * Provides the app/build.gradle for modification.
179 *
180 * @param config
181 * @param action
182 */
183export const withAppBuildGradle: ConfigPlugin<Mod<Paths.GradleProjectFile>> = (config, action) => {
184  return withMod(config, {
185    platform: 'android',
186    mod: 'appBuildGradle',
187    action,
188  });
189};
190
191/**
192 * Provides the /settings.gradle for modification.
193 *
194 * @param config
195 * @param action
196 */
197export const withSettingsGradle: ConfigPlugin<Mod<Paths.GradleProjectFile>> = (config, action) => {
198  return withMod(config, {
199    platform: 'android',
200    mod: 'settingsGradle',
201    action,
202  });
203};
204
205/**
206 * Provides the /gradle.properties for modification.
207 *
208 * @param config
209 * @param action
210 */
211export const withGradleProperties: ConfigPlugin<Mod<Properties.PropertiesItem[]>> = (
212  config,
213  action
214) => {
215  return withMod(config, {
216    platform: 'android',
217    mod: 'gradleProperties',
218    action,
219  });
220};
221