This repository has been archived on 2026-10-08. You can view files and clone it, but cannot push or open issues or pull requests.
allotment/packages/app/plugins/withSceneLifecycle.js

56 lines
1.8 KiB
JavaScript

const { withAppDelegate, withInfoPlist } = require('expo/config-plugins');
/**
* iOS 27 aborts at launch unless the app adopts the UIScene life cycle. Expo
* ships `ExpoAppSceneDelegate` for this, but the SDK 57 template still starts
* React Native from the app delegate, so register the scene delegate and let it
* own the window.
*/
function withSceneManifest(config) {
return withInfoPlist(config, (cfg) => {
cfg.modResults.UIApplicationSceneManifest = {
UIApplicationSupportsMultipleScenes: false,
UISceneConfigurations: {
UIWindowSceneSessionRoleApplication: [
{
UISceneConfigurationName: 'Default Configuration',
UISceneDelegateClassName: 'EXExpoAppSceneDelegate',
},
],
},
};
return cfg;
});
}
function withSceneAppDelegate(config) {
return withAppDelegate(config, (cfg) => {
if (cfg.modResults.language !== 'swift') {
throw new Error('withSceneLifecycle only supports a Swift AppDelegate');
}
let src = cfg.modResults.contents;
if (!src.includes('ExpoReactNativeFactoryProvider')) {
src = src.replace(
/class AppDelegate: ExpoAppDelegate \{/,
'class AppDelegate: ExpoAppDelegate, ExpoReactNativeFactoryProvider {',
);
}
src = src.replace(
/\n#if os\(iOS\) \|\| os\(tvOS\)\n\s*window = UIWindow\(frame: UIScreen\.main\.bounds\)\n\s*factory\.startReactNative\([\s\S]*?\)\n#endif\n/,
'',
);
if (!src.includes('ExpoReactNativeFactoryProvider') || src.includes('UIWindow(frame: UIScreen.main.bounds)')) {
throw new Error('withSceneLifecycle could not patch AppDelegate.swift; the Expo template has changed');
}
cfg.modResults.contents = src;
return cfg;
});
}
module.exports = function withSceneLifecycle(config) {
return withSceneAppDelegate(withSceneManifest(config));
};