1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3    return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const config_plugins_1 = require("@expo/config-plugins");
7const fs_1 = __importDefault(require("fs"));
8const path_1 = __importDefault(require("path"));
9const semver_1 = __importDefault(require("semver"));
10const resolveExpoUpdatesVersion_1 = require("./resolveExpoUpdatesVersion");
11const withDevLauncherAppDelegate_1 = require("./withDevLauncherAppDelegate");
12const pkg = require('expo-dev-launcher/package.json');
13const DEV_LAUNCHER_ANDROID_IMPORT = 'expo.modules.devlauncher.DevLauncherController';
14const DEV_LAUNCHER_UPDATES_ANDROID_IMPORT = 'expo.modules.updates.UpdatesDevLauncherController';
15const DEV_LAUNCHER_ON_NEW_INTENT = `
16  @Override
17  public void onNewIntent(Intent intent) {
18      if (DevLauncherController.tryToHandleIntent(this, intent)) {
19         return;
20      }
21      super.onNewIntent(intent);
22  }
23`;
24const DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE = `DevLauncherController.wrapReactActivityDelegate(this, () -> $1);`;
25const DEV_LAUNCHER_ANDROID_INIT = 'DevLauncherController.initialize(this, getReactNativeHost());';
26const DEV_LAUNCHER_UPDATES_ANDROID_INIT = 'DevLauncherController.getInstance().setUpdatesInterface(UpdatesDevLauncherController.initialize(this));';
27const DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT = 'return DevLauncherController.getInstance().getUseDeveloperSupport();';
28const DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS = `import 'expo-dev-client';`;
29async function readFileAsync(path) {
30    return fs_1.default.promises.readFile(path, 'utf8');
31}
32async function saveFileAsync(path, content) {
33    return fs_1.default.promises.writeFile(path, content, 'utf8');
34}
35function addLines(content, find, offset, toAdd) {
36    const lines = content.split('\n');
37    let lineIndex = lines.findIndex(line => line.match(find));
38    for (const newLine of toAdd) {
39        if (!content.includes(newLine)) {
40            lines.splice(lineIndex + offset, 0, newLine);
41            lineIndex++;
42        }
43    }
44    return lines.join('\n');
45}
46function replaceLine(content, find, replace) {
47    const lines = content.split('\n');
48    if (!content.includes(replace)) {
49        const lineIndex = lines.findIndex(line => line.match(find));
50        lines.splice(lineIndex, 1, replace);
51    }
52    return lines.join('\n');
53}
54function addJavaImports(javaSource, javaImports) {
55    const lines = javaSource.split('\n');
56    const lineIndexWithPackageDeclaration = lines.findIndex(line => line.match(/^package .*;$/));
57    for (const javaImport of javaImports) {
58        if (!javaSource.includes(javaImport)) {
59            const importStatement = `import ${javaImport};`;
60            lines.splice(lineIndexWithPackageDeclaration + 1, 0, importStatement);
61        }
62    }
63    return lines.join('\n');
64}
65async function editMainApplication(config, action) {
66    const mainApplicationPath = path_1.default.join(config.modRequest.platformProjectRoot, 'app', 'src', 'main', 'java', ...config.android.package.split('.'), 'MainApplication.java');
67    try {
68        const mainApplication = action(await readFileAsync(mainApplicationPath));
69        return await saveFileAsync(mainApplicationPath, mainApplication);
70    }
71    catch (e) {
72        config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify MainApplication.java - ${e}.`);
73    }
74}
75async function editPodfile(config, action) {
76    const podfilePath = path_1.default.join(config.modRequest.platformProjectRoot, 'Podfile');
77    try {
78        const podfile = action(await readFileAsync(podfilePath));
79        return await saveFileAsync(podfilePath, podfile);
80    }
81    catch (e) {
82        config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify AppDelegate.m - ${e}.`);
83    }
84}
85async function editIndex(config, action) {
86    const indexPath = path_1.default.join(config.modRequest.projectRoot, 'index.js');
87    try {
88        const index = action(await readFileAsync(indexPath));
89        return await saveFileAsync(indexPath, index);
90    }
91    catch (e) {
92        config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify index.js - ${e}.`);
93    }
94}
95const withDevLauncherApplication = config => {
96    return config_plugins_1.withDangerousMod(config, [
97        'android',
98        async (config) => {
99            await editMainApplication(config, mainApplication => {
100                mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_ANDROID_IMPORT]);
101                mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
102                    `    ${DEV_LAUNCHER_ANDROID_INIT}`,
103                ]);
104                let expoUpdatesVersion;
105                try {
106                    expoUpdatesVersion = resolveExpoUpdatesVersion_1.resolveExpoUpdatesVersion(config.modRequest.projectRoot);
107                }
108                catch (e) {
109                    config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Failed to check compatibility with expo-updates - ${e}`);
110                }
111                if (expoUpdatesVersion && semver_1.default.gt(expoUpdatesVersion, '0.6.0')) {
112                    mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_UPDATES_ANDROID_IMPORT]);
113                    mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
114                        `    ${DEV_LAUNCHER_UPDATES_ANDROID_INIT}`,
115                    ]);
116                    mainApplication = replaceLine(mainApplication, 'return BuildConfig.DEBUG;', `      ${DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT}`);
117                }
118                return mainApplication;
119            });
120            return config;
121        },
122    ]);
123};
124const withDevLauncherActivity = config => {
125    return config_plugins_1.withMainActivity(config, config => {
126        if (config.modResults.language === 'java') {
127            let content = addJavaImports(config.modResults.contents, [
128                DEV_LAUNCHER_ANDROID_IMPORT,
129                'android.content.Intent',
130            ]);
131            if (!content.includes(DEV_LAUNCHER_ON_NEW_INTENT)) {
132                const lines = content.split('\n');
133                const onCreateIndex = lines.findIndex(line => line.includes('public class MainActivity'));
134                lines.splice(onCreateIndex + 1, 0, DEV_LAUNCHER_ON_NEW_INTENT);
135                content = lines.join('\n');
136            }
137            if (!content.includes('DevLauncherController.wrapReactActivityDelegate')) {
138                content = content.replace(/(new ReactActivityDelegate(.*|\s)*});$/m, DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE);
139            }
140            config.modResults.contents = content;
141        }
142        else {
143            config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Cannot automatically configure MainActivity if it's not java`);
144        }
145        return config;
146    });
147};
148const withDevLauncherPodfile = config => {
149    return config_plugins_1.withDangerousMod(config, [
150        'ios',
151        async (config) => {
152            await editPodfile(config, podfile => {
153                podfile = podfile.replace("platform :ios, '10.0'", "platform :ios, '11.0'");
154                // Match both variations of Ruby config:
155                // unknown: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', :configurations => :debug
156                // Rubocop: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', configurations: :debug
157                if (!podfile.match(/pod ['"]expo-dev-launcher['"],\s?path: ['"][^'"]*node_modules\/expo-dev-launcher['"],\s?:?configurations:?\s(?:=>\s)?:debug/)) {
158                    const packagePath = path_1.default.dirname(require.resolve('expo-dev-launcher/package.json'));
159                    const relativePath = path_1.default.relative(config.modRequest.platformProjectRoot, packagePath);
160                    podfile = addLines(podfile, 'use_react_native', 0, [
161                        `  pod 'expo-dev-launcher', path: '${relativePath}', :configurations => :debug`,
162                    ]);
163                }
164                return podfile;
165            });
166            return config;
167        },
168    ]);
169};
170const withErrorHandling = config => {
171    return config_plugins_1.withDangerousMod(config, [
172        // We want to edit js file, but for the `DangerousMod` we need to select a platform.
173        'android',
174        async (config) => {
175            await editIndex(config, index => {
176                if (!index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS)) {
177                    index = DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS + '\n\n' + index;
178                }
179                return index;
180            });
181            return config;
182        },
183    ]);
184};
185const withDevLauncher = (config) => {
186    config = withDevLauncherActivity(config);
187    config = withDevLauncherApplication(config);
188    config = withDevLauncherPodfile(config);
189    config = withDevLauncherAppDelegate_1.withDevLauncherAppDelegate(config);
190    config = withErrorHandling(config);
191    return config;
192};
193exports.default = config_plugins_1.createRunOncePlugin(withDevLauncher, pkg.name, pkg.version);
194