expo-dev-launcher 0.7.0 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/README.md +1 -1
- package/android/build.gradle +2 -1
- package/android/src/debug/assets/expo_dev_launcher_android.bundle +396 -403
- package/android/src/debug/java/expo/modules/devlauncher/DevLauncherController.kt +10 -6
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactory.kt +5 -5
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherExpoAppLoader.kt +5 -5
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherLocalAppLoader.kt +3 -3
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherPublishedAppLoader.kt +2 -6
- package/android/src/debug/java/expo/modules/devlauncher/modules/DevLauncherInternalModule.kt +6 -1
- package/android/src/debug/java/expo/modules/devlauncher/modules/DevLauncherModule.kt +1 -1
- package/android/src/main/java/expo/modules/devlauncher/launcher/DevLauncherControllerInterface.kt +2 -2
- package/android/src/main/java/expo/modules/devlauncher/launcher/configurators/DevLauncherExpoActivityConfigurator.kt +12 -11
- package/android/src/main/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifestParser.kt +4 -2
- package/android/src/main/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifestTypes.kt +11 -26
- package/android/src/main/java/expo/modules/devlauncher/launcher/menu/DevLauncherMenuDelegate.kt +3 -3
- package/android/src/release/java/expo/modules/devlauncher/DevLauncherController.kt +2 -2
- package/android/src/testDebug/java/expo/modules/devlauncher/DevLauncherControllerTest.kt +50 -0
- package/android/src/testDebug/java/expo/modules/devlauncher/launcher/DevLauncherRecentlyOpenedAppsRegistryTest.kt +43 -0
- package/android/src/testDebug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactoryTest.kt +3 -3
- package/android/src/testDebug/java/expo/modules/devlauncher/modules/DevLauncherModuleTest.kt +38 -0
- package/build/DevLauncherErrorManager.js +7 -0
- package/build/DevLauncherErrorManager.js.map +1 -1
- package/expo-dev-launcher.podspec +2 -0
- package/ios/EXDevLauncher.m +8 -2
- package/ios/EXDevLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/EXDevLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/EXDevLauncher.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/ios/EXDevLauncher.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/EXDevLauncherController.h +2 -2
- package/ios/EXDevLauncherController.m +22 -11
- package/ios/EXDevLauncherInternal.m +5 -0
- package/ios/EXDevLauncherMenuDelegate.swift +3 -3
- package/ios/Errors/EXDevLauncherRedBox.m +5 -0
- package/ios/Manifest/EXDevLauncherManifestHelper.swift +15 -12
- package/ios/Manifest/EXDevLauncherManifestParser.h +3 -3
- package/ios/Manifest/EXDevLauncherManifestParser.m +17 -5
- package/ios/Tests/EXDevLauncherManifestHelperTests.swift +28 -0
- package/ios/Tests/EXDevLauncherManifestParserTests.m +113 -0
- package/ios/Tests/EXDevLauncherModuleTests.m +39 -0
- package/ios/devvyc 2021-05-14 18-19-10/devvyc.ipa +0 -0
- package/ios/main.jsbundle +414 -420
- package/package.json +6 -6
- package/plugin/build/constants.d.ts +1 -0
- package/plugin/build/constants.js +4 -0
- package/plugin/build/utils.d.ts +2 -0
- package/plugin/build/utils.js +24 -0
- package/plugin/build/withDevLauncher.js +27 -39
- package/plugin/build/withDevLauncherAppDelegate.d.ts +1 -0
- package/plugin/build/withDevLauncherAppDelegate.js +161 -16
- package/plugin/src/constants.ts +1 -0
- package/plugin/src/utils.ts +25 -0
- package/plugin/src/withDevLauncher.ts +32 -45
- package/plugin/src/withDevLauncherAppDelegate.ts +211 -23
- package/src/DevLauncherErrorManager.ts +7 -0
- package/android/src/main/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifest.kt +0 -111
- package/ios/Manifest/EXDevLauncherManifest.swift +0 -158
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-dev-launcher",
|
|
3
3
|
"title": "Expo Development Launcher",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.3",
|
|
5
5
|
"description": "Pre-release version of the Expo development launcher package for testing.",
|
|
6
6
|
"main": "build/DevLauncher.js",
|
|
7
7
|
"types": "build/DevLauncher.d.ts",
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"homepage": "https://docs.expo.io",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@expo/config-plugins": "^3.
|
|
31
|
+
"@expo/config-plugins": "^3.1.0",
|
|
32
32
|
"resolve-from": "^5.0.0",
|
|
33
33
|
"semver": "^7.3.5"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"babel-preset-expo": "~8.
|
|
36
|
+
"babel-preset-expo": "~8.5.1",
|
|
37
37
|
"expo-module-scripts": "^2.0.0",
|
|
38
|
-
"react": "
|
|
39
|
-
"react-native": "0.
|
|
38
|
+
"react": "17.0.1",
|
|
39
|
+
"react-native": "0.64.2"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "7adf260ab3de492530d4bf250a24b132b5c4ba41"
|
|
42
42
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const InstallationPage = "https://docs.expo.dev/clients/installation/";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.replaceLine = exports.addLines = void 0;
|
|
4
|
+
function addLines(content, find, offset, toAdd) {
|
|
5
|
+
const lines = content.split('\n');
|
|
6
|
+
let lineIndex = lines.findIndex((line) => line.match(find));
|
|
7
|
+
for (const newLine of toAdd) {
|
|
8
|
+
if (!content.includes(newLine)) {
|
|
9
|
+
lines.splice(lineIndex + offset, 0, newLine);
|
|
10
|
+
lineIndex++;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return lines.join('\n');
|
|
14
|
+
}
|
|
15
|
+
exports.addLines = addLines;
|
|
16
|
+
function replaceLine(content, find, replace) {
|
|
17
|
+
const lines = content.split('\n');
|
|
18
|
+
if (!content.includes(replace)) {
|
|
19
|
+
const lineIndex = lines.findIndex((line) => line.match(find));
|
|
20
|
+
lines.splice(lineIndex, 1, replace);
|
|
21
|
+
}
|
|
22
|
+
return lines.join('\n');
|
|
23
|
+
}
|
|
24
|
+
exports.replaceLine = replaceLine;
|
|
@@ -7,7 +7,9 @@ const config_plugins_1 = require("@expo/config-plugins");
|
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const semver_1 = __importDefault(require("semver"));
|
|
10
|
+
const constants_1 = require("./constants");
|
|
10
11
|
const resolveExpoUpdatesVersion_1 = require("./resolveExpoUpdatesVersion");
|
|
12
|
+
const utils_1 = require("./utils");
|
|
11
13
|
const withDevLauncherAppDelegate_1 = require("./withDevLauncherAppDelegate");
|
|
12
14
|
const pkg = require('expo-dev-launcher/package.json');
|
|
13
15
|
const DEV_LAUNCHER_ANDROID_IMPORT = 'expo.modules.devlauncher.DevLauncherController';
|
|
@@ -35,28 +37,9 @@ async function readFileAsync(path) {
|
|
|
35
37
|
async function saveFileAsync(path, content) {
|
|
36
38
|
return fs_1.default.promises.writeFile(path, content, 'utf8');
|
|
37
39
|
}
|
|
38
|
-
function addLines(content, find, offset, toAdd) {
|
|
39
|
-
const lines = content.split('\n');
|
|
40
|
-
let lineIndex = lines.findIndex(line => line.match(find));
|
|
41
|
-
for (const newLine of toAdd) {
|
|
42
|
-
if (!content.includes(newLine)) {
|
|
43
|
-
lines.splice(lineIndex + offset, 0, newLine);
|
|
44
|
-
lineIndex++;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return lines.join('\n');
|
|
48
|
-
}
|
|
49
|
-
function replaceLine(content, find, replace) {
|
|
50
|
-
const lines = content.split('\n');
|
|
51
|
-
if (!content.includes(replace)) {
|
|
52
|
-
const lineIndex = lines.findIndex(line => line.match(find));
|
|
53
|
-
lines.splice(lineIndex, 1, replace);
|
|
54
|
-
}
|
|
55
|
-
return lines.join('\n');
|
|
56
|
-
}
|
|
57
40
|
function addJavaImports(javaSource, javaImports) {
|
|
58
41
|
const lines = javaSource.split('\n');
|
|
59
|
-
const lineIndexWithPackageDeclaration = lines.findIndex(line => line.match(/^package .*;$/));
|
|
42
|
+
const lineIndexWithPackageDeclaration = lines.findIndex((line) => line.match(/^package .*;$/));
|
|
60
43
|
for (const javaImport of javaImports) {
|
|
61
44
|
if (!javaSource.includes(javaImport)) {
|
|
62
45
|
const importStatement = `import ${javaImport};`;
|
|
@@ -72,7 +55,8 @@ async function editMainApplication(config, action) {
|
|
|
72
55
|
return await saveFileAsync(mainApplicationPath, mainApplication);
|
|
73
56
|
}
|
|
74
57
|
catch (e) {
|
|
75
|
-
config_plugins_1.WarningAggregator.
|
|
58
|
+
config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Couldn't modify MainApplication.java - ${e}.
|
|
59
|
+
See the expo-dev-client installation instructions to modify your MainApplication.java manually: ${constants_1.InstallationPage}`);
|
|
76
60
|
}
|
|
77
61
|
}
|
|
78
62
|
async function editPodfile(config, action) {
|
|
@@ -82,7 +66,8 @@ async function editPodfile(config, action) {
|
|
|
82
66
|
return await saveFileAsync(podfilePath, podfile);
|
|
83
67
|
}
|
|
84
68
|
catch (e) {
|
|
85
|
-
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify AppDelegate.m - ${e}
|
|
69
|
+
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify AppDelegate.m - ${e}.
|
|
70
|
+
See the expo-dev-client installation instructions to modify your AppDelegate.m manually: ${constants_1.InstallationPage}`);
|
|
86
71
|
}
|
|
87
72
|
}
|
|
88
73
|
async function editIndex(config, action) {
|
|
@@ -92,16 +77,17 @@ async function editIndex(config, action) {
|
|
|
92
77
|
return await saveFileAsync(indexPath, index);
|
|
93
78
|
}
|
|
94
79
|
catch (e) {
|
|
95
|
-
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify index.js - ${e}
|
|
80
|
+
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify index.js - ${e}.
|
|
81
|
+
See the expo-dev-client installation instructions to modify your index.js manually: ${constants_1.InstallationPage}`);
|
|
96
82
|
}
|
|
97
83
|
}
|
|
98
|
-
const withDevLauncherApplication = config => {
|
|
84
|
+
const withDevLauncherApplication = (config) => {
|
|
99
85
|
return config_plugins_1.withDangerousMod(config, [
|
|
100
86
|
'android',
|
|
101
87
|
async (config) => {
|
|
102
|
-
await editMainApplication(config, mainApplication => {
|
|
88
|
+
await editMainApplication(config, (mainApplication) => {
|
|
103
89
|
mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_ANDROID_IMPORT]);
|
|
104
|
-
mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
|
|
90
|
+
mainApplication = utils_1.addLines(mainApplication, 'initializeFlipper\\(this', 0, [
|
|
105
91
|
` ${DEV_LAUNCHER_ANDROID_INIT}`,
|
|
106
92
|
]);
|
|
107
93
|
let expoUpdatesVersion;
|
|
@@ -113,10 +99,10 @@ const withDevLauncherApplication = config => {
|
|
|
113
99
|
}
|
|
114
100
|
if (expoUpdatesVersion && semver_1.default.gt(expoUpdatesVersion, '0.6.0')) {
|
|
115
101
|
mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_UPDATES_ANDROID_IMPORT]);
|
|
116
|
-
mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
|
|
102
|
+
mainApplication = utils_1.addLines(mainApplication, 'initializeFlipper\\(this', 0, [
|
|
117
103
|
` ${DEV_LAUNCHER_UPDATES_ANDROID_INIT}`,
|
|
118
104
|
]);
|
|
119
|
-
mainApplication = replaceLine(mainApplication, 'return BuildConfig.DEBUG;', ` ${DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT}`);
|
|
105
|
+
mainApplication = utils_1.replaceLine(mainApplication, 'return BuildConfig.DEBUG;', ` ${DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT}`);
|
|
120
106
|
}
|
|
121
107
|
return mainApplication;
|
|
122
108
|
});
|
|
@@ -124,8 +110,8 @@ const withDevLauncherApplication = config => {
|
|
|
124
110
|
},
|
|
125
111
|
]);
|
|
126
112
|
};
|
|
127
|
-
const withDevLauncherActivity = config => {
|
|
128
|
-
return config_plugins_1.withMainActivity(config, config => {
|
|
113
|
+
const withDevLauncherActivity = (config) => {
|
|
114
|
+
return config_plugins_1.withMainActivity(config, (config) => {
|
|
129
115
|
if (config.modResults.language === 'java') {
|
|
130
116
|
let content = addJavaImports(config.modResults.contents, [
|
|
131
117
|
DEV_LAUNCHER_ANDROID_IMPORT,
|
|
@@ -133,34 +119,36 @@ const withDevLauncherActivity = config => {
|
|
|
133
119
|
]);
|
|
134
120
|
if (!content.includes(DEV_LAUNCHER_ON_NEW_INTENT)) {
|
|
135
121
|
const lines = content.split('\n');
|
|
136
|
-
const onCreateIndex = lines.findIndex(line => line.includes('public class MainActivity'));
|
|
122
|
+
const onCreateIndex = lines.findIndex((line) => line.includes('public class MainActivity'));
|
|
137
123
|
lines.splice(onCreateIndex + 1, 0, DEV_LAUNCHER_ON_NEW_INTENT);
|
|
138
124
|
content = lines.join('\n');
|
|
139
125
|
}
|
|
140
126
|
if (!content.includes('DevLauncherController.wrapReactActivityDelegate')) {
|
|
141
|
-
content = content.replace(/(new ReactActivityDelegate(
|
|
127
|
+
content = content.replace(/(new ReactActivityDelegate(Wrapper)?(.|\s)*\}\)?);$/mu, DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE);
|
|
142
128
|
}
|
|
143
129
|
config.modResults.contents = content;
|
|
144
130
|
}
|
|
145
131
|
else {
|
|
146
|
-
config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Cannot automatically configure MainActivity if it's not java
|
|
132
|
+
config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Cannot automatically configure MainActivity if it's not java.
|
|
133
|
+
See the expo-dev-client installation instructions to modify your MainActivity manually: ${constants_1.InstallationPage}`);
|
|
147
134
|
}
|
|
148
135
|
return config;
|
|
149
136
|
});
|
|
150
137
|
};
|
|
151
|
-
const withDevLauncherPodfile = config => {
|
|
138
|
+
const withDevLauncherPodfile = (config) => {
|
|
152
139
|
return config_plugins_1.withDangerousMod(config, [
|
|
153
140
|
'ios',
|
|
154
141
|
async (config) => {
|
|
155
|
-
await editPodfile(config, podfile => {
|
|
156
|
-
|
|
142
|
+
await editPodfile(config, (podfile) => {
|
|
143
|
+
// replace all iOS versions below 12
|
|
144
|
+
podfile = podfile.replace(/platform :ios, '((\d\.0)|(1[0-1].0))'/, "platform :ios, '12.0'");
|
|
157
145
|
// Match both variations of Ruby config:
|
|
158
146
|
// unknown: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', :configurations => :debug
|
|
159
147
|
// Rubocop: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', configurations: :debug
|
|
160
148
|
if (!podfile.match(/pod ['"]expo-dev-launcher['"],\s?path: ['"][^'"]*node_modules\/expo-dev-launcher['"],\s?:?configurations:?\s(?:=>\s)?:debug/)) {
|
|
161
149
|
const packagePath = path_1.default.dirname(require.resolve('expo-dev-launcher/package.json'));
|
|
162
150
|
const relativePath = path_1.default.relative(config.modRequest.platformProjectRoot, packagePath);
|
|
163
|
-
podfile = addLines(podfile, 'use_react_native', 0, [
|
|
151
|
+
podfile = utils_1.addLines(podfile, 'use_react_native', 0, [
|
|
164
152
|
` pod 'expo-dev-launcher', path: '${relativePath}', :configurations => :debug`,
|
|
165
153
|
]);
|
|
166
154
|
}
|
|
@@ -170,9 +158,9 @@ const withDevLauncherPodfile = config => {
|
|
|
170
158
|
},
|
|
171
159
|
]);
|
|
172
160
|
};
|
|
173
|
-
const withErrorHandling = config => {
|
|
161
|
+
const withErrorHandling = (config) => {
|
|
174
162
|
const injectErrorHandlers = async (config) => {
|
|
175
|
-
await editIndex(config, index => {
|
|
163
|
+
await editIndex(config, (index) => {
|
|
176
164
|
if (!index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS) &&
|
|
177
165
|
!index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS_VIA_LAUNCHER)) {
|
|
178
166
|
index = DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS + ';\n\n' + index;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
export declare function modifyLegacyAppDelegate(appDelegate: string, expoUpdatesVersion?: string | null): string;
|
|
2
3
|
export declare function modifyAppDelegate(appDelegate: string, expoUpdatesVersion?: string | null): string;
|
|
3
4
|
export declare const withDevLauncherAppDelegate: ConfigPlugin;
|
|
@@ -3,10 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.withDevLauncherAppDelegate = exports.modifyAppDelegate = void 0;
|
|
6
|
+
exports.withDevLauncherAppDelegate = exports.modifyAppDelegate = exports.modifyLegacyAppDelegate = void 0;
|
|
7
7
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
8
8
|
const semver_1 = __importDefault(require("semver"));
|
|
9
|
+
const constants_1 = require("./constants");
|
|
9
10
|
const resolveExpoUpdatesVersion_1 = require("./resolveExpoUpdatesVersion");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
function escapeRegExpCharacters(string) {
|
|
13
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
14
|
+
}
|
|
15
|
+
const INITIALIZE_REACT_NATIVE_APP_FUNCTION = `- (RCTBridge *)initializeReactNativeApp`;
|
|
16
|
+
const NEW_INITIALIZE_REACT_NATIVE_APP_FUNCTION = `- (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions`;
|
|
10
17
|
const DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL = ` #if defined(EX_DEV_LAUNCHER_ENABLED)
|
|
11
18
|
return [[EXDevLauncherController sharedInstance] sourceUrl];
|
|
12
19
|
#else
|
|
@@ -27,7 +34,7 @@ const DEV_LAUNCHER_UPDATES_APP_DELEGATE_IOS_IMPORT = `
|
|
|
27
34
|
#include <EXDevLauncher/EXDevLauncherController.h>
|
|
28
35
|
#import <EXUpdates/EXUpdatesDevLauncherController.h>
|
|
29
36
|
#endif`;
|
|
30
|
-
const
|
|
37
|
+
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY = `
|
|
31
38
|
#if defined(EX_DEV_LAUNCHER_ENABLED)
|
|
32
39
|
@implementation AppDelegate (EXDevLauncherControllerDelegate)
|
|
33
40
|
|
|
@@ -39,6 +46,19 @@ const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE = `
|
|
|
39
46
|
[splashScreenService showSplashScreenFor:self.window.rootViewController];
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
@end
|
|
50
|
+
#endif
|
|
51
|
+
`;
|
|
52
|
+
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE = `
|
|
53
|
+
#if defined(EX_DEV_LAUNCHER_ENABLED)
|
|
54
|
+
@implementation AppDelegate (EXDevLauncherControllerDelegate)
|
|
55
|
+
|
|
56
|
+
- (void)devLauncherController:(EXDevLauncherController *)developmentClientController
|
|
57
|
+
didStartWithSuccess:(BOOL)success
|
|
58
|
+
{
|
|
59
|
+
developmentClientController.appBridge = [self initializeReactNativeApp:[EXDevLauncherController.sharedInstance getLaunchOptions]];
|
|
60
|
+
}
|
|
61
|
+
|
|
42
62
|
@end
|
|
43
63
|
#endif
|
|
44
64
|
`;
|
|
@@ -62,8 +82,72 @@ const DEV_MENU_IOS_INIT = `
|
|
|
62
82
|
#if defined(EX_DEV_MENU_ENABLED)
|
|
63
83
|
[DevMenuManager configureWithBridge:bridge];
|
|
64
84
|
#endif`;
|
|
65
|
-
|
|
66
|
-
|
|
85
|
+
const DEV_LAUNCHER_INIT_TO_REMOVE = new RegExp(escapeRegExpCharacters(`RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
|
|
86
|
+
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil];
|
|
87
|
+
id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
|
|
88
|
+
if (rootViewBackgroundColor != nil) {
|
|
89
|
+
rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
|
|
90
|
+
} else {
|
|
91
|
+
rootView.backgroundColor = [UIColor whiteColor];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
|
95
|
+
UIViewController *rootViewController = `) +
|
|
96
|
+
`([^;]+)` +
|
|
97
|
+
escapeRegExpCharacters(`;
|
|
98
|
+
rootViewController.view = rootView;
|
|
99
|
+
self.window.rootViewController = rootViewController;
|
|
100
|
+
[self.window makeKeyAndVisible];`), 'm');
|
|
101
|
+
const DEV_LAUNCHER_NEW_INIT = `self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
|
102
|
+
#if defined(EX_DEV_LAUNCHER_ENABLED)
|
|
103
|
+
EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];
|
|
104
|
+
[controller startWithWindow:self.window delegate:(id<EXDevLauncherControllerDelegate>)self launchOptions:launchOptions];
|
|
105
|
+
#else
|
|
106
|
+
[self initializeReactNativeApp:launchOptions];
|
|
107
|
+
#endif`;
|
|
108
|
+
const DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION_REGEX = new RegExp(escapeRegExpCharacters(`
|
|
109
|
+
- (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions
|
|
110
|
+
{
|
|
111
|
+
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
|
|
112
|
+
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil];
|
|
113
|
+
id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
|
|
114
|
+
if (rootViewBackgroundColor != nil) {
|
|
115
|
+
rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
|
|
116
|
+
} else {
|
|
117
|
+
rootView.backgroundColor = [UIColor whiteColor];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
UIViewController *rootViewController = `) +
|
|
121
|
+
`[^;]+` +
|
|
122
|
+
escapeRegExpCharacters(`;
|
|
123
|
+
rootViewController.view = rootView;
|
|
124
|
+
self.window.rootViewController = rootViewController;
|
|
125
|
+
[self.window makeKeyAndVisible];
|
|
126
|
+
|
|
127
|
+
return bridge;
|
|
128
|
+
}
|
|
129
|
+
`), 'm');
|
|
130
|
+
const DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION = (viewControllerInit) => `
|
|
131
|
+
- (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions
|
|
132
|
+
{
|
|
133
|
+
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
|
|
134
|
+
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil];
|
|
135
|
+
id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
|
|
136
|
+
if (rootViewBackgroundColor != nil) {
|
|
137
|
+
rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
|
|
138
|
+
} else {
|
|
139
|
+
rootView.backgroundColor = [UIColor whiteColor];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
UIViewController *rootViewController = ${viewControllerInit !== null && viewControllerInit !== void 0 ? viewControllerInit : '[UIViewController new]'};
|
|
143
|
+
rootViewController.view = rootView;
|
|
144
|
+
self.window.rootViewController = rootViewController;
|
|
145
|
+
[self.window makeKeyAndVisible];
|
|
146
|
+
|
|
147
|
+
return bridge;
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
function addImports(appDelegate, shouldAddUpdatesIntegration) {
|
|
67
151
|
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_IOS_IMPORT) &&
|
|
68
152
|
!appDelegate.includes(DEV_LAUNCHER_UPDATES_APP_DELEGATE_IOS_IMPORT)) {
|
|
69
153
|
const lines = appDelegate.split('\n');
|
|
@@ -72,6 +156,31 @@ function modifyAppDelegate(appDelegate, expoUpdatesVersion = null) {
|
|
|
72
156
|
: DEV_LAUNCHER_APP_DELEGATE_IOS_IMPORT);
|
|
73
157
|
appDelegate = lines.join('\n');
|
|
74
158
|
}
|
|
159
|
+
return appDelegate;
|
|
160
|
+
}
|
|
161
|
+
function removeDevMenuInit(appDelegate) {
|
|
162
|
+
if (!appDelegate.includes(DEV_MENU_IMPORT)) {
|
|
163
|
+
// expo-dev-launcher is responsible for initializing the expo-dev-menu.
|
|
164
|
+
// We need to remove init block from AppDelegate.
|
|
165
|
+
appDelegate = appDelegate.replace(DEV_MENU_IOS_INIT, '');
|
|
166
|
+
}
|
|
167
|
+
return appDelegate;
|
|
168
|
+
}
|
|
169
|
+
function addDeepLinkHandler(appDelegate) {
|
|
170
|
+
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
|
|
171
|
+
appDelegate = appDelegate.replace('return [RCTLinkingManager application:application openURL:url options:options];', DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK);
|
|
172
|
+
}
|
|
173
|
+
return appDelegate;
|
|
174
|
+
}
|
|
175
|
+
function changeDebugURL(appDelegate) {
|
|
176
|
+
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL)) {
|
|
177
|
+
appDelegate = appDelegate.replace('return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];', DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL);
|
|
178
|
+
}
|
|
179
|
+
return appDelegate;
|
|
180
|
+
}
|
|
181
|
+
function modifyLegacyAppDelegate(appDelegate, expoUpdatesVersion = null) {
|
|
182
|
+
const shouldAddUpdatesIntegration = expoUpdatesVersion != null && semver_1.default.gt(expoUpdatesVersion, '0.6.0');
|
|
183
|
+
appDelegate = addImports(appDelegate, shouldAddUpdatesIntegration);
|
|
75
184
|
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_INIT)) {
|
|
76
185
|
appDelegate = appDelegate.replace(/(didFinishLaunchingWithOptions([^}])*)\[self initializeReactNativeApp\];(([^}])*})/, `$1${DEV_LAUNCHER_APP_DELEGATE_INIT}$3`);
|
|
77
186
|
}
|
|
@@ -82,25 +191,53 @@ function modifyAppDelegate(appDelegate, expoUpdatesVersion = null) {
|
|
|
82
191
|
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_BRIDGE)) {
|
|
83
192
|
appDelegate = appDelegate.replace('RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:self.launchOptions];', DEV_LAUNCHER_APP_DELEGATE_BRIDGE);
|
|
84
193
|
}
|
|
85
|
-
|
|
86
|
-
|
|
194
|
+
appDelegate = changeDebugURL(appDelegate);
|
|
195
|
+
appDelegate = addDeepLinkHandler(appDelegate);
|
|
196
|
+
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY)) {
|
|
197
|
+
appDelegate += DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY;
|
|
87
198
|
}
|
|
88
|
-
|
|
89
|
-
|
|
199
|
+
appDelegate = removeDevMenuInit(appDelegate);
|
|
200
|
+
return appDelegate;
|
|
201
|
+
}
|
|
202
|
+
exports.modifyLegacyAppDelegate = modifyLegacyAppDelegate;
|
|
203
|
+
function modifyAppDelegate(appDelegate, expoUpdatesVersion = null) {
|
|
204
|
+
const shouldAddUpdatesIntegration = expoUpdatesVersion != null && semver_1.default.gt(expoUpdatesVersion, '0.6.0');
|
|
205
|
+
if (!DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION_REGEX.test(appDelegate)) {
|
|
206
|
+
if (DEV_LAUNCHER_INIT_TO_REMOVE.test(appDelegate)) {
|
|
207
|
+
// UIViewController can be initialized differently depending on whether expo-screen-orientation is installed,
|
|
208
|
+
// so we need to preserve whatever is there already.
|
|
209
|
+
let viewControllerInit;
|
|
210
|
+
appDelegate = appDelegate.replace(DEV_LAUNCHER_INIT_TO_REMOVE, (match, p1) => {
|
|
211
|
+
viewControllerInit = p1;
|
|
212
|
+
return DEV_LAUNCHER_NEW_INIT;
|
|
213
|
+
});
|
|
214
|
+
appDelegate = utils_1.addLines(appDelegate, '@implementation AppDelegate', 1, [
|
|
215
|
+
DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION(viewControllerInit),
|
|
216
|
+
]);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Failed to modify AppDelegate init function.
|
|
220
|
+
See the expo-dev-client installation instructions to modify your AppDelegate manually: ${constants_1.InstallationPage}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (shouldAddUpdatesIntegration &&
|
|
224
|
+
!appDelegate.includes(DEV_LAUNCHER_UPDATES_APP_DELEGATE_INIT)) {
|
|
225
|
+
appDelegate = appDelegate.replace('EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];', DEV_LAUNCHER_UPDATES_APP_DELEGATE_INIT);
|
|
90
226
|
}
|
|
227
|
+
appDelegate = addImports(appDelegate, shouldAddUpdatesIntegration);
|
|
91
228
|
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE)) {
|
|
92
229
|
appDelegate += DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE;
|
|
93
230
|
}
|
|
94
|
-
if (!appDelegate.includes(
|
|
95
|
-
|
|
96
|
-
// We need to remove init block from AppDelegate.
|
|
97
|
-
appDelegate = appDelegate.replace(DEV_MENU_IOS_INIT, '');
|
|
231
|
+
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
|
|
232
|
+
appDelegate = appDelegate.replace('return [RCTLinkingManager application:application openURL:url options:options];', DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK);
|
|
98
233
|
}
|
|
234
|
+
appDelegate = changeDebugURL(appDelegate);
|
|
235
|
+
appDelegate = removeDevMenuInit(appDelegate);
|
|
99
236
|
return appDelegate;
|
|
100
237
|
}
|
|
101
238
|
exports.modifyAppDelegate = modifyAppDelegate;
|
|
102
|
-
|
|
103
|
-
return config_plugins_1.withAppDelegate(config, config => {
|
|
239
|
+
const withDevLauncherAppDelegate = (config) => {
|
|
240
|
+
return config_plugins_1.withAppDelegate(config, (config) => {
|
|
104
241
|
if (config.modResults.language === 'objc') {
|
|
105
242
|
let expoUpdatesVersion;
|
|
106
243
|
try {
|
|
@@ -109,11 +246,19 @@ exports.withDevLauncherAppDelegate = config => {
|
|
|
109
246
|
catch (e) {
|
|
110
247
|
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Failed to check compatibility with expo-updates - ${e}`);
|
|
111
248
|
}
|
|
112
|
-
|
|
249
|
+
if (config.modResults.contents.includes(INITIALIZE_REACT_NATIVE_APP_FUNCTION) &&
|
|
250
|
+
!config.modResults.contents.includes(NEW_INITIALIZE_REACT_NATIVE_APP_FUNCTION)) {
|
|
251
|
+
config.modResults.contents = modifyLegacyAppDelegate(config.modResults.contents, expoUpdatesVersion);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
config.modResults.contents = modifyAppDelegate(config.modResults.contents, expoUpdatesVersion);
|
|
255
|
+
}
|
|
113
256
|
}
|
|
114
257
|
else {
|
|
115
|
-
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher',
|
|
258
|
+
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Swift AppDelegate files are not supported yet.
|
|
259
|
+
See the expo-dev-client installation instructions to modify your AppDelegate manually: ${constants_1.InstallationPage}`);
|
|
116
260
|
}
|
|
117
261
|
return config;
|
|
118
262
|
});
|
|
119
263
|
};
|
|
264
|
+
exports.withDevLauncherAppDelegate = withDevLauncherAppDelegate;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const InstallationPage = 'https://docs.expo.dev/clients/installation/';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function addLines(content: string, find: string | RegExp, offset: number, toAdd: string[]) {
|
|
2
|
+
const lines = content.split('\n');
|
|
3
|
+
|
|
4
|
+
let lineIndex = lines.findIndex((line) => line.match(find));
|
|
5
|
+
|
|
6
|
+
for (const newLine of toAdd) {
|
|
7
|
+
if (!content.includes(newLine)) {
|
|
8
|
+
lines.splice(lineIndex + offset, 0, newLine);
|
|
9
|
+
lineIndex++;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return lines.join('\n');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function replaceLine(content: string, find: string | RegExp, replace: string) {
|
|
17
|
+
const lines = content.split('\n');
|
|
18
|
+
|
|
19
|
+
if (!content.includes(replace)) {
|
|
20
|
+
const lineIndex = lines.findIndex((line) => line.match(find));
|
|
21
|
+
lines.splice(lineIndex, 1, replace);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return lines.join('\n');
|
|
25
|
+
}
|