Skip to content

Commit

Permalink
[config][dev-launcher] Fix compatibility with SDK 44
Browse files Browse the repository at this point in the history
  • Loading branch information
lukmccall committed Dec 14, 2021
1 parent efb05e9 commit 05bdedb
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 10 deletions.
35 changes: 33 additions & 2 deletions packages/expo-dev-launcher/plugin/build/withDevLauncher.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 50 additions & 4 deletions packages/expo-dev-launcher/plugin/src/withDevLauncher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const DEV_LAUNCHER_HANDLE_INTENT = [
' return;',
' }',
].join('\n');
const DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE = `DevLauncherController.wrapReactActivityDelegate(this, () -> $1);`;
const DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE = (activityDelegateDeclaration: string) =>
`DevLauncherController.wrapReactActivityDelegate(this, () -> ${activityDelegateDeclaration})`;
const DEV_LAUNCHER_ANDROID_INIT = 'DevLauncherController.initialize(this, getReactNativeHost());';
const DEV_LAUNCHER_UPDATES_ANDROID_INIT = `if (BuildConfig.DEBUG) {
DevLauncherController.getInstance().setUpdatesInterface(UpdatesDevLauncherController.initialize(this));
Expand All @@ -52,6 +53,29 @@ async function saveFileAsync(path: string, content: string): Promise<void> {
return fs.promises.writeFile(path, content, 'utf8');
}

function findClosingBracketMatchIndex(str: string, pos: number) {
if (str[pos] !== '(') {
throw new Error("No '(' at index " + pos);
}
let depth = 1;
for (let i = pos + 1; i < str.length; i++) {
switch (str[i]) {
case '(':
depth++;
break;
case ')':
if (--depth === 0) {
return i;
}
break;
}
}
return -1; // No matching closing parenthesis
}

const replaceBetween = (origin: string, startIndex: number, endIndex: number, insertion: string) =>
`${origin.substring(0, startIndex)}${insertion}${origin.substring(endIndex)}`;

function addJavaImports(javaSource: string, javaImports: string[]): string {
const lines = javaSource.split('\n');
const lineIndexWithPackageDeclaration = lines.findIndex((line) => line.match(/^package .*;$/));
Expand Down Expand Up @@ -173,9 +197,31 @@ export function modifyJavaMainActivity(content: string): string {
}

if (!content.includes('DevLauncherController.wrapReactActivityDelegate')) {
content = content.replace(
/(new ReactActivityDelegate(Wrapper)?(.|\s)*\}\)?);$/mu,
DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE
const activityDelegateMatches = Array.from(
content.matchAll(/new ReactActivityDelegate(Wrapper)/g)
);

if (activityDelegateMatches.length !== 1) {
WarningAggregator.addWarningAndroid(
'expo-dev-launcher',
`Failed to wrap 'ReactActivityDelegate'
See the expo-dev-client installation instructions to modify your MainApplication.java manually: ${InstallationPage}`
);
return content;
}

const activityDelegateMatch = activityDelegateMatches[0];
const matchIndex = activityDelegateMatch.index!;
const openingBracketIndex = matchIndex + activityDelegateMatch[0].length; // next character after `new ReactActivityDelegateWrapper`

const closingBracketIndex = findClosingBracketMatchIndex(content, openingBracketIndex);
const reactActivityDelegateDeclaration = content.substring(matchIndex, closingBracketIndex + 1);

content = replaceBetween(
content,
matchIndex,
closingBracketIndex + 1,
DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE(reactActivityDelegateDeclaration)
);
}
return content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ const DEV_LAUNCHER_INIT_TO_REMOVE = new RegExp(
'm'
);

const DEV_LAUNCHER_INIT_TO_REMOVE_SDK_44 = new RegExp(
escapeRegExpCharacters(`RCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [self.reactDelegate createRootViewWithBridge:bridge moduleName:@"main" initialProperties:nil];
rootView.backgroundColor = [UIColor whiteColor];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = `) +
`([^;]+)` +
escapeRegExpCharacters(`;
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];`),
'm'
);

const DEV_LAUNCHER_NEW_INIT = `self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
#if defined(EX_DEV_LAUNCHER_ENABLED)
EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];
Expand Down Expand Up @@ -260,11 +274,18 @@ export function modifyAppDelegate(appDelegate: string, expoUpdatesVersion: strin
expoUpdatesVersion != null && semver.gt(expoUpdatesVersion, '0.6.0');

if (!DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION_REGEX.test(appDelegate)) {
if (DEV_LAUNCHER_INIT_TO_REMOVE.test(appDelegate)) {
let initToRemove;
if (DEV_LAUNCHER_INIT_TO_REMOVE_SDK_44.test(appDelegate)) {
initToRemove = DEV_LAUNCHER_INIT_TO_REMOVE_SDK_44;
} else if (DEV_LAUNCHER_INIT_TO_REMOVE.test(appDelegate)) {
initToRemove = DEV_LAUNCHER_APP_DELEGATE_BRIDGE;
}

if (initToRemove) {
// UIViewController can be initialized differently depending on whether expo-screen-orientation is installed,
// so we need to preserve whatever is there already.
let viewControllerInit;
appDelegate = appDelegate.replace(DEV_LAUNCHER_INIT_TO_REMOVE, (match, p1) => {
appDelegate = appDelegate.replace(initToRemove, (match, p1) => {
viewControllerInit = p1;
return DEV_LAUNCHER_NEW_INIT;
});
Expand Down

0 comments on commit 05bdedb

Please sign in to comment.