This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,105 @@
import { ExpoConfig } from '@expo/config-types';
import { JSONObject } from '@expo/json-file';
import { XcodeProject } from 'xcode';
import { Properties } from './android';
import { AndroidManifest } from './android/Manifest';
import * as AndroidPaths from './android/Paths';
import { ResourceXML } from './android/Resources';
import { ExpoPlist, InfoPlist } from './ios/IosConfig.types';
import { AppDelegateProjectFile } from './ios/Paths';
declare type OptionalPromise<T> = Promise<T> | T;
declare type Plist = JSONObject;
export interface ModProps<T = any> {
/**
* Project root directory for the universal app.
*/
readonly projectRoot: string;
/**
* Project root for the specific platform.
*/
readonly platformProjectRoot: string;
/**
* Name of the mod.
*/
readonly modName: string;
/**
* Name of the platform used in the mods config.
*/
readonly platform: ModPlatform;
/**
* [iOS]: The path component used for querying project files.
*
* @example projectRoot/ios/[projectName]/
*/
readonly projectName?: string;
nextMod?: Mod<T>;
}
export interface ExportedConfig extends ExpoConfig {
mods?: ModConfig | null;
}
export interface ExportedConfigWithProps<Data = any> extends ExpoConfig {
/**
* The Object representation of a complex file type.
*/
modResults: Data;
modRequest: ModProps<Data>;
}
export declare type ConfigPlugin<Props = void> = (config: ExpoConfig, props: Props) => ExpoConfig;
export declare type StaticPlugin<T = any> = [string | ConfigPlugin<T>, T];
export declare type Mod<Props = any> = (config: ExportedConfigWithProps<Props>) => OptionalPromise<ExportedConfigWithProps<Props>>;
export interface ModConfig {
android?: {
/**
* Modify the `android/app/src/main/AndroidManifest.xml` as JSON (parsed with [`xml2js`](https://www.npmjs.com/package/xml2js)).
*/
manifest?: Mod<AndroidManifest>;
/**
* Modify the `android/app/src/main/res/values/strings.xml` as JSON (parsed with [`xml2js`](https://www.npmjs.com/package/xml2js)).
*/
strings?: Mod<ResourceXML>;
/**
* Modify the `android/app/src/main/<package>/MainActivity.java` as a string.
*/
mainActivity?: Mod<AndroidPaths.ApplicationProjectFile>;
/**
* Modify the `android/app/build.gradle` as a string.
*/
appBuildGradle?: Mod<AndroidPaths.GradleProjectFile>;
/**
* Modify the `android/build.gradle` as a string.
*/
projectBuildGradle?: Mod<AndroidPaths.GradleProjectFile>;
/**
* Modify the `android/settings.gradle` as a string.
*/
settingsGradle?: Mod<AndroidPaths.GradleProjectFile>;
/**
* Modify the `android/gradle.properties` as a `Properties.PropertiesItem[]`.
*/
gradleProperties?: Mod<Properties.PropertiesItem[]>;
};
ios?: {
/**
* Modify the `ios/<name>/Info.plist` as JSON (parsed with [`@expo/plist`](https://www.npmjs.com/package/@expo/plist)).
*/
infoPlist?: Mod<InfoPlist>;
/**
* Modify the `ios/<name>/<product-name>.entitlements` as JSON (parsed with [`@expo/plist`](https://www.npmjs.com/package/@expo/plist)).
*/
entitlements?: Mod<Plist>;
/**
* Modify the `ios/<name>/Expo.plist` as JSON (Expo updates config for iOS) (parsed with [`@expo/plist`](https://www.npmjs.com/package/@expo/plist)).
*/
expoPlist?: Mod<Plist>;
/**
* Modify the `ios/<name>.xcodeproj` as an `XcodeProject` (parsed with [`xcode`](https://www.npmjs.com/package/xcode))
*/
xcodeproj?: Mod<XcodeProject>;
/**
* Modify the `ios/<name>/AppDelegate.m` as a string (dangerous)
*/
appDelegate?: Mod<AppDelegateProjectFile>;
};
}
export declare type ModPlatform = keyof ModConfig;
export { XcodeProject, InfoPlist, ExpoPlist, AndroidManifest };

View File

@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const xcode_1 = require("xcode");
exports.XcodeProject = xcode_1.XcodeProject;
//# sourceMappingURL=Plugin.types.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Plugin.types.js","sourceRoot":"","sources":["../src/Plugin.types.ts"],"names":[],"mappings":";;AAEA,iCAAqC;AA0H5B,uBA1HA,oBAAY,CA0HA","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\nimport { JSONObject } from '@expo/json-file';\nimport { XcodeProject } from 'xcode';\n\nimport { Properties } from './android';\nimport { AndroidManifest } from './android/Manifest';\nimport * as AndroidPaths from './android/Paths';\nimport { ResourceXML } from './android/Resources';\nimport { ExpoPlist, InfoPlist } from './ios/IosConfig.types';\nimport { AppDelegateProjectFile } from './ios/Paths';\n\ntype OptionalPromise<T> = Promise<T> | T;\n\ntype Plist = JSONObject;\n\nexport interface ModProps<T = any> {\n /**\n * Project root directory for the universal app.\n */\n readonly projectRoot: string;\n\n /**\n * Project root for the specific platform.\n */\n readonly platformProjectRoot: string;\n\n /**\n * Name of the mod.\n */\n readonly modName: string;\n\n /**\n * Name of the platform used in the mods config.\n */\n readonly platform: ModPlatform;\n\n /**\n * [iOS]: The path component used for querying project files.\n *\n * @example projectRoot/ios/[projectName]/\n */\n readonly projectName?: string;\n\n nextMod?: Mod<T>;\n}\n\n// TODO: Migrate ProjectConfig to using expo instead if exp\nexport interface ExportedConfig extends ExpoConfig {\n mods?: ModConfig | null;\n}\n\nexport interface ExportedConfigWithProps<Data = any> extends ExpoConfig {\n /**\n * The Object representation of a complex file type.\n */\n modResults: Data;\n modRequest: ModProps<Data>;\n}\n\nexport type ConfigPlugin<Props = void> = (config: ExpoConfig, props: Props) => ExpoConfig;\n\nexport type StaticPlugin<T = any> = [string | ConfigPlugin<T>, T];\n\nexport type Mod<Props = any> = (\n config: ExportedConfigWithProps<Props>\n) => OptionalPromise<ExportedConfigWithProps<Props>>;\n\nexport interface ModConfig {\n android?: {\n /**\n * Modify the `android/app/src/main/AndroidManifest.xml` as JSON (parsed with [`xml2js`](https://www.npmjs.com/package/xml2js)).\n */\n manifest?: Mod<AndroidManifest>;\n /**\n * Modify the `android/app/src/main/res/values/strings.xml` as JSON (parsed with [`xml2js`](https://www.npmjs.com/package/xml2js)).\n */\n strings?: Mod<ResourceXML>;\n /**\n * Modify the `android/app/src/main/<package>/MainActivity.java` as a string.\n */\n mainActivity?: Mod<AndroidPaths.ApplicationProjectFile>;\n /**\n * Modify the `android/app/build.gradle` as a string.\n */\n appBuildGradle?: Mod<AndroidPaths.GradleProjectFile>;\n /**\n * Modify the `android/build.gradle` as a string.\n */\n projectBuildGradle?: Mod<AndroidPaths.GradleProjectFile>;\n /**\n * Modify the `android/settings.gradle` as a string.\n */\n settingsGradle?: Mod<AndroidPaths.GradleProjectFile>;\n /**\n * Modify the `android/gradle.properties` as a `Properties.PropertiesItem[]`.\n */\n gradleProperties?: Mod<Properties.PropertiesItem[]>;\n };\n ios?: {\n /**\n * Modify the `ios/<name>/Info.plist` as JSON (parsed with [`@expo/plist`](https://www.npmjs.com/package/@expo/plist)).\n */\n infoPlist?: Mod<InfoPlist>;\n /**\n * Modify the `ios/<name>/<product-name>.entitlements` as JSON (parsed with [`@expo/plist`](https://www.npmjs.com/package/@expo/plist)).\n */\n entitlements?: Mod<Plist>;\n /**\n * Modify the `ios/<name>/Expo.plist` as JSON (Expo updates config for iOS) (parsed with [`@expo/plist`](https://www.npmjs.com/package/@expo/plist)).\n */\n expoPlist?: Mod<Plist>;\n /**\n * Modify the `ios/<name>.xcodeproj` as an `XcodeProject` (parsed with [`xcode`](https://www.npmjs.com/package/xcode))\n */\n xcodeproj?: Mod<XcodeProject>;\n /**\n * Modify the `ios/<name>/AppDelegate.m` as a string (dangerous)\n */\n appDelegate?: Mod<AppDelegateProjectFile>;\n };\n}\n\nexport type ModPlatform = keyof ModConfig;\n\nexport { XcodeProject, InfoPlist, ExpoPlist, AndroidManifest };\n"]}

View File

@ -0,0 +1,6 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
export declare const withAdMob: import("..").ConfigPlugin<void>;
export declare function getGoogleMobileAdsAppId(config: Pick<ExpoConfig, 'android'>): string | null;
export declare function getGoogleMobileAdsAutoInit(config: Pick<ExpoConfig, 'android'>): boolean;
export declare function setAdMobConfig(config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidManifest): AndroidManifest;

View File

@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const Manifest_1 = require("./Manifest");
const META_APPLICATION_ID = 'com.google.android.gms.ads.APPLICATION_ID';
const META_DELAY_APP_MEASUREMENT_INIT = 'com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT';
exports.withAdMob = android_plugins_1.createAndroidManifestPlugin(setAdMobConfig, 'withAdMob');
function getGoogleMobileAdsAppId(config) {
var _a, _b, _c;
return (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.googleMobileAdsAppId) !== null && _c !== void 0 ? _c : null;
}
exports.getGoogleMobileAdsAppId = getGoogleMobileAdsAppId;
function getGoogleMobileAdsAutoInit(config) {
var _a, _b, _c;
return (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.googleMobileAdsAutoInit) !== null && _c !== void 0 ? _c : false;
}
exports.getGoogleMobileAdsAutoInit = getGoogleMobileAdsAutoInit;
function setAdMobConfig(config, androidManifest) {
const appId = getGoogleMobileAdsAppId(config);
const autoInit = getGoogleMobileAdsAutoInit(config);
const mainApplication = Manifest_1.getMainApplicationOrThrow(androidManifest);
if (appId) {
Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_APPLICATION_ID, appId);
Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_DELAY_APP_MEASUREMENT_INIT, String(!autoInit));
}
else {
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_APPLICATION_ID);
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_DELAY_APP_MEASUREMENT_INIT);
}
return androidManifest;
}
exports.setAdMobConfig = setAdMobConfig;
//# sourceMappingURL=AdMob.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"AdMob.js","sourceRoot":"","sources":["../../src/android/AdMob.ts"],"names":[],"mappings":";;AAEA,gEAAyE;AACzE,yCAKoB;AAEpB,MAAM,mBAAmB,GAAG,2CAA2C,CAAC;AACxE,MAAM,+BAA+B,GAAG,uDAAuD,CAAC;AAEnF,QAAA,SAAS,GAAG,6CAA2B,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAElF,SAAgB,uBAAuB,CAAC,MAAmC;;IACzE,yBAAO,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,oBAAoB,mCAAI,IAAI,CAAC;AAC9D,CAAC;AAFD,0DAEC;AAED,SAAgB,0BAA0B,CAAC,MAAmC;;IAC5E,yBAAO,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,uBAAuB,mCAAI,KAAK,CAAC;AAClE,CAAC;AAFD,gEAEC;AAED,SAAgB,cAAc,CAC5B,MAAmC,EACnC,eAAgC;IAEhC,MAAM,KAAK,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,eAAe,GAAG,oCAAyB,CAAC,eAAe,CAAC,CAAC;IAEnE,IAAI,KAAK,EAAE;QACT,2CAAgC,CAAC,eAAe,EAAE,mBAAmB,EAAE,KAAK,CAAC,CAAC;QAC9E,2CAAgC,CAC9B,eAAe,EACf,+BAA+B,EAC/B,MAAM,CAAC,CAAC,QAAQ,CAAC,CAClB,CAAC;KACH;SAAM;QACL,gDAAqC,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;QAC5E,gDAAqC,CAAC,eAAe,EAAE,+BAA+B,CAAC,CAAC;KACzF;IAED,OAAO,eAAe,CAAC;AACzB,CAAC;AArBD,wCAqBC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { createAndroidManifestPlugin } from '../plugins/android-plugins';\nimport {\n addMetaDataItemToMainApplication,\n AndroidManifest,\n getMainApplicationOrThrow,\n removeMetaDataItemFromMainApplication,\n} from './Manifest';\n\nconst META_APPLICATION_ID = 'com.google.android.gms.ads.APPLICATION_ID';\nconst META_DELAY_APP_MEASUREMENT_INIT = 'com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT';\n\nexport const withAdMob = createAndroidManifestPlugin(setAdMobConfig, 'withAdMob');\n\nexport function getGoogleMobileAdsAppId(config: Pick<ExpoConfig, 'android'>) {\n return config.android?.config?.googleMobileAdsAppId ?? null;\n}\n\nexport function getGoogleMobileAdsAutoInit(config: Pick<ExpoConfig, 'android'>) {\n return config.android?.config?.googleMobileAdsAutoInit ?? false;\n}\n\nexport function setAdMobConfig(\n config: Pick<ExpoConfig, 'android'>,\n androidManifest: AndroidManifest\n) {\n const appId = getGoogleMobileAdsAppId(config);\n const autoInit = getGoogleMobileAdsAutoInit(config);\n const mainApplication = getMainApplicationOrThrow(androidManifest);\n\n if (appId) {\n addMetaDataItemToMainApplication(mainApplication, META_APPLICATION_ID, appId);\n addMetaDataItemToMainApplication(\n mainApplication,\n META_DELAY_APP_MEASUREMENT_INIT,\n String(!autoInit)\n );\n } else {\n removeMetaDataItemFromMainApplication(mainApplication, META_APPLICATION_ID);\n removeMetaDataItemFromMainApplication(mainApplication, META_DELAY_APP_MEASUREMENT_INIT);\n }\n\n return androidManifest;\n}\n"]}

View File

@ -0,0 +1,6 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
export declare const withAllowBackup: import("..").ConfigPlugin<void>;
export declare function getAllowBackup(config: Pick<ExpoConfig, 'android'>): boolean;
export declare function setAllowBackup(config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidManifest): AndroidManifest;
export declare function getAllowBackupFromManifest(androidManifest: AndroidManifest): boolean | null;

View File

@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const Manifest_1 = require("./Manifest");
exports.withAllowBackup = android_plugins_1.createAndroidManifestPlugin(setAllowBackup, 'withAllowBackup');
function getAllowBackup(config) {
var _a, _b;
// Defaults to true.
// https://docs.expo.io/versions/latest/config/app/#allowbackup
return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.allowBackup) !== null && _b !== void 0 ? _b : true;
}
exports.getAllowBackup = getAllowBackup;
function setAllowBackup(config, androidManifest) {
const allowBackup = getAllowBackup(config);
const mainApplication = Manifest_1.getMainApplication(androidManifest);
if (mainApplication === null || mainApplication === void 0 ? void 0 : mainApplication.$) {
mainApplication.$['android:allowBackup'] = String(allowBackup);
}
return androidManifest;
}
exports.setAllowBackup = setAllowBackup;
function getAllowBackupFromManifest(androidManifest) {
const mainApplication = Manifest_1.getMainApplication(androidManifest);
if (mainApplication === null || mainApplication === void 0 ? void 0 : mainApplication.$) {
return String(mainApplication.$['android:allowBackup']) === 'true';
}
return null;
}
exports.getAllowBackupFromManifest = getAllowBackupFromManifest;
//# sourceMappingURL=AllowBackup.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"AllowBackup.js","sourceRoot":"","sources":["../../src/android/AllowBackup.ts"],"names":[],"mappings":";;AAEA,gEAAyE;AACzE,yCAAgF;AAEnE,QAAA,eAAe,GAAG,6CAA2B,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;AAE9F,SAAgB,cAAc,CAAC,MAAmC;;IAChE,oBAAoB;IACpB,+DAA+D;IAC/D,mBAAO,MAAM,CAAC,OAAO,0CAAE,WAAW,mCAAI,IAAI,CAAC;AAC7C,CAAC;AAJD,wCAIC;AAED,SAAgB,cAAc,CAC5B,MAAmC,EACnC,eAAgC;IAEhC,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,eAAe,GAAG,6BAAkB,CAAC,eAAe,CAAC,CAAC;IAC5D,IAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,CAAC,EAAE;QACtB,eAAe,CAAC,CAAC,CAAC,qBAAqB,CAAC,GAAG,MAAM,CAAC,WAAW,CAAkB,CAAC;KACjF;IAED,OAAO,eAAe,CAAC;AACzB,CAAC;AAZD,wCAYC;AAED,SAAgB,0BAA0B,CAAC,eAAgC;IACzE,MAAM,eAAe,GAAG,6BAAkB,CAAC,eAAe,CAAC,CAAC;IAE5D,IAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,CAAC,EAAE;QACtB,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,KAAK,MAAM,CAAC;KACpE;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AARD,gEAQC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { createAndroidManifestPlugin } from '../plugins/android-plugins';\nimport { AndroidManifest, getMainApplication, StringBoolean } from './Manifest';\n\nexport const withAllowBackup = createAndroidManifestPlugin(setAllowBackup, 'withAllowBackup');\n\nexport function getAllowBackup(config: Pick<ExpoConfig, 'android'>) {\n // Defaults to true.\n // https://docs.expo.io/versions/latest/config/app/#allowbackup\n return config.android?.allowBackup ?? true;\n}\n\nexport function setAllowBackup(\n config: Pick<ExpoConfig, 'android'>,\n androidManifest: AndroidManifest\n) {\n const allowBackup = getAllowBackup(config);\n\n const mainApplication = getMainApplication(androidManifest);\n if (mainApplication?.$) {\n mainApplication.$['android:allowBackup'] = String(allowBackup) as StringBoolean;\n }\n\n return androidManifest;\n}\n\nexport function getAllowBackupFromManifest(androidManifest: AndroidManifest): boolean | null {\n const mainApplication = getMainApplication(androidManifest);\n\n if (mainApplication?.$) {\n return String(mainApplication.$['android:allowBackup']) === 'true';\n }\n\n return null;\n}\n"]}

View File

@ -0,0 +1,5 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
export declare const withBranch: import("..").ConfigPlugin<void>;
export declare function getBranchApiKey(config: ExpoConfig): string | null;
export declare function setBranchApiKey(config: ExpoConfig, androidManifest: AndroidManifest): AndroidManifest;

View File

@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const Manifest_1 = require("./Manifest");
const META_BRANCH_KEY = 'io.branch.sdk.BranchKey';
exports.withBranch = android_plugins_1.createAndroidManifestPlugin(setBranchApiKey, 'withBranch');
function getBranchApiKey(config) {
var _a, _b, _c, _d;
return (_d = (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.branch) === null || _c === void 0 ? void 0 : _c.apiKey) !== null && _d !== void 0 ? _d : null;
}
exports.getBranchApiKey = getBranchApiKey;
function setBranchApiKey(config, androidManifest) {
const apiKey = getBranchApiKey(config);
const mainApplication = Manifest_1.getMainApplicationOrThrow(androidManifest);
if (apiKey) {
// If the item exists, add it back
Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_BRANCH_KEY, apiKey);
}
else {
// Remove any existing item
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_BRANCH_KEY);
}
return androidManifest;
}
exports.setBranchApiKey = setBranchApiKey;
//# sourceMappingURL=Branch.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Branch.js","sourceRoot":"","sources":["../../src/android/Branch.ts"],"names":[],"mappings":";;AAEA,gEAAyE;AACzE,yCAKoB;AAEpB,MAAM,eAAe,GAAG,yBAAyB,CAAC;AAErC,QAAA,UAAU,GAAG,6CAA2B,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;AAErF,SAAgB,eAAe,CAAC,MAAkB;;IAChD,+BAAO,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,MAAM,0CAAE,MAAM,mCAAI,IAAI,CAAC;AACxD,CAAC;AAFD,0CAEC;AAED,SAAgB,eAAe,CAAC,MAAkB,EAAE,eAAgC;IAClF,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAEvC,MAAM,eAAe,GAAG,oCAAyB,CAAC,eAAe,CAAC,CAAC;IAEnE,IAAI,MAAM,EAAE;QACV,kCAAkC;QAClC,2CAAgC,CAAC,eAAe,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;KAC5E;SAAM;QACL,2BAA2B;QAC3B,gDAAqC,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;KACzE;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAbD,0CAaC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { createAndroidManifestPlugin } from '../plugins/android-plugins';\nimport {\n addMetaDataItemToMainApplication,\n AndroidManifest,\n getMainApplicationOrThrow,\n removeMetaDataItemFromMainApplication,\n} from './Manifest';\n\nconst META_BRANCH_KEY = 'io.branch.sdk.BranchKey';\n\nexport const withBranch = createAndroidManifestPlugin(setBranchApiKey, 'withBranch');\n\nexport function getBranchApiKey(config: ExpoConfig) {\n return config.android?.config?.branch?.apiKey ?? null;\n}\n\nexport function setBranchApiKey(config: ExpoConfig, androidManifest: AndroidManifest) {\n const apiKey = getBranchApiKey(config);\n\n const mainApplication = getMainApplicationOrThrow(androidManifest);\n\n if (apiKey) {\n // If the item exists, add it back\n addMetaDataItemToMainApplication(mainApplication, META_BRANCH_KEY, apiKey);\n } else {\n // Remove any existing item\n removeMetaDataItemFromMainApplication(mainApplication, META_BRANCH_KEY);\n }\n return androidManifest;\n}\n"]}

View File

@ -0,0 +1,6 @@
import { ResourceItemXML, ResourceKind, ResourceXML } from './Resources';
export declare function getProjectColorsXMLPathAsync(projectRoot: string, { kind }?: {
kind?: ResourceKind;
}): Promise<string>;
export declare function setColorItem(itemToAdd: ResourceItemXML, colorFileContentsJSON: ResourceXML): ResourceXML;
export declare function removeColorItem(named: string, contents: ResourceXML): ResourceXML;

View File

@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Paths_1 = require("./Paths");
function getProjectColorsXMLPathAsync(projectRoot, { kind } = {}) {
return Paths_1.getResourceXMLPathAsync(projectRoot, { kind, name: 'colors' });
}
exports.getProjectColorsXMLPathAsync = getProjectColorsXMLPathAsync;
function setColorItem(itemToAdd, colorFileContentsJSON) {
var _a;
if ((_a = colorFileContentsJSON.resources) === null || _a === void 0 ? void 0 : _a.color) {
const colorNameExists = colorFileContentsJSON.resources.color.filter((e) => e.$.name === itemToAdd.$.name)[0];
if (colorNameExists) {
colorNameExists._ = itemToAdd._;
}
else {
colorFileContentsJSON.resources.color.push(itemToAdd);
}
}
else {
if (!colorFileContentsJSON.resources || typeof colorFileContentsJSON.resources === 'string') {
//file was empty and JSON is `{resources : ''}`
colorFileContentsJSON.resources = {};
}
colorFileContentsJSON.resources.color = [itemToAdd];
}
return colorFileContentsJSON;
}
exports.setColorItem = setColorItem;
function removeColorItem(named, contents) {
var _a;
if ((_a = contents.resources) === null || _a === void 0 ? void 0 : _a.color) {
const index = contents.resources.color.findIndex((e) => e.$.name === named);
if (index > -1) {
// replace the previous value
contents.resources.color.splice(index, 1);
}
}
return contents;
}
exports.removeColorItem = removeColorItem;
//# sourceMappingURL=Colors.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Colors.js","sourceRoot":"","sources":["../../src/android/Colors.ts"],"names":[],"mappings":";;AAAA,mCAAkD;AAGlD,SAAgB,4BAA4B,CAC1C,WAAmB,EACnB,EAAE,IAAI,KAA8B,EAAE;IAEtC,OAAO,+BAAuB,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AACxE,CAAC;AALD,oEAKC;AAED,SAAgB,YAAY,CAAC,SAA0B,EAAE,qBAAkC;;IACzF,UAAI,qBAAqB,CAAC,SAAS,0CAAE,KAAK,EAAE;QAC1C,MAAM,eAAe,GAAG,qBAAqB,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAClE,CAAC,CAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CACtD,CAAC,CAAC,CAAC,CAAC;QACL,IAAI,eAAe,EAAE;YACnB,eAAe,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;SACjC;aAAM;YACL,qBAAqB,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;SACvD;KACF;SAAM;QACL,IAAI,CAAC,qBAAqB,CAAC,SAAS,IAAI,OAAO,qBAAqB,CAAC,SAAS,KAAK,QAAQ,EAAE;YAC3F,+CAA+C;YAC/C,qBAAqB,CAAC,SAAS,GAAG,EAAE,CAAC;SACtC;QACD,qBAAqB,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;KACrD;IACD,OAAO,qBAAqB,CAAC;AAC/B,CAAC;AAlBD,oCAkBC;AAED,SAAgB,eAAe,CAAC,KAAa,EAAE,QAAqB;;IAClE,UAAI,QAAQ,CAAC,SAAS,0CAAE,KAAK,EAAE;QAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;QAC7F,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;YACd,6BAA6B;YAC7B,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;SAC3C;KACF;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AATD,0CASC","sourcesContent":["import { getResourceXMLPathAsync } from './Paths';\nimport { ResourceItemXML, ResourceKind, ResourceXML } from './Resources';\n\nexport function getProjectColorsXMLPathAsync(\n projectRoot: string,\n { kind }: { kind?: ResourceKind } = {}\n) {\n return getResourceXMLPathAsync(projectRoot, { kind, name: 'colors' });\n}\n\nexport function setColorItem(itemToAdd: ResourceItemXML, colorFileContentsJSON: ResourceXML) {\n if (colorFileContentsJSON.resources?.color) {\n const colorNameExists = colorFileContentsJSON.resources.color.filter(\n (e: ResourceItemXML) => e.$.name === itemToAdd.$.name\n )[0];\n if (colorNameExists) {\n colorNameExists._ = itemToAdd._;\n } else {\n colorFileContentsJSON.resources.color.push(itemToAdd);\n }\n } else {\n if (!colorFileContentsJSON.resources || typeof colorFileContentsJSON.resources === 'string') {\n //file was empty and JSON is `{resources : ''}`\n colorFileContentsJSON.resources = {};\n }\n colorFileContentsJSON.resources.color = [itemToAdd];\n }\n return colorFileContentsJSON;\n}\n\nexport function removeColorItem(named: string, contents: ResourceXML) {\n if (contents.resources?.color) {\n const index = contents.resources.color.findIndex((e: ResourceItemXML) => e.$.name === named);\n if (index > -1) {\n // replace the previous value\n contents.resources.color.splice(index, 1);\n }\n }\n return contents;\n}\n"]}

View File

@ -0,0 +1,3 @@
export declare function getEasBuildGradlePath(projectRoot: string): string;
export declare function configureEasBuildAsync(projectRoot: string): Promise<void>;
export declare function isEasBuildGradleConfiguredAsync(projectRoot: string): Promise<boolean>;

View File

@ -0,0 +1,49 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const EasBuildGradleScript_1 = __importDefault(require("./EasBuildGradleScript"));
const Paths = __importStar(require("./Paths"));
const APPLY_EAS_GRADLE = 'apply from: "./eas-build.gradle"';
function hasApplyLine(content, applyLine) {
return (content
.replace(/\r\n/g, '\n')
.split('\n')
// Check for both single and double quotes
.some(line => line === applyLine || line === applyLine.replace(/"/g, "'")));
}
function getEasBuildGradlePath(projectRoot) {
return path_1.default.join(projectRoot, 'android', 'app', 'eas-build.gradle');
}
exports.getEasBuildGradlePath = getEasBuildGradlePath;
async function configureEasBuildAsync(projectRoot) {
const buildGradlePath = Paths.getAppBuildGradle(projectRoot);
const easGradlePath = getEasBuildGradlePath(projectRoot);
await fs_extra_1.default.writeFile(easGradlePath, EasBuildGradleScript_1.default);
const buildGradleContent = await fs_extra_1.default.readFile(path_1.default.join(buildGradlePath), 'utf8');
const hasEasGradleApply = hasApplyLine(buildGradleContent, APPLY_EAS_GRADLE);
if (!hasEasGradleApply) {
await fs_extra_1.default.writeFile(buildGradlePath, `${buildGradleContent.trim()}\n${APPLY_EAS_GRADLE}\n`);
}
}
exports.configureEasBuildAsync = configureEasBuildAsync;
async function isEasBuildGradleConfiguredAsync(projectRoot) {
const buildGradlePath = Paths.getAppBuildGradle(projectRoot);
const easGradlePath = getEasBuildGradlePath(projectRoot);
const hasEasGradleFile = await fs_extra_1.default.pathExists(easGradlePath);
const buildGradleContent = await fs_extra_1.default.readFile(path_1.default.join(buildGradlePath), 'utf8');
const hasEasGradleApply = hasApplyLine(buildGradleContent, APPLY_EAS_GRADLE);
return hasEasGradleApply && hasEasGradleFile;
}
exports.isEasBuildGradleConfiguredAsync = isEasBuildGradleConfiguredAsync;
//# sourceMappingURL=EasBuild.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"EasBuild.js","sourceRoot":"","sources":["../../src/android/EasBuild.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,wDAA0B;AAC1B,gDAAwB;AAExB,kFAAkD;AAClD,+CAAiC;AAEjC,MAAM,gBAAgB,GAAG,kCAAkC,CAAC;AAE5D,SAAS,YAAY,CAAC,OAAe,EAAE,SAAiB;IACtD,OAAO,CACL,OAAO;SACJ,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;SACtB,KAAK,CAAC,IAAI,CAAC;QACZ,0CAA0C;SACzC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAC7E,CAAC;AACJ,CAAC;AAED,SAAgB,qBAAqB,CAAC,WAAmB;IACvD,OAAO,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC;AACtE,CAAC;AAFD,sDAEC;AAEM,KAAK,UAAU,sBAAsB,CAAC,WAAmB;IAC9D,MAAM,eAAe,GAAG,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAEzD,MAAM,kBAAE,CAAC,SAAS,CAAC,aAAa,EAAE,8BAAY,CAAC,CAAC;IAEhD,MAAM,kBAAkB,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,cAAI,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;IAEjF,MAAM,iBAAiB,GAAG,YAAY,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IAE7E,IAAI,CAAC,iBAAiB,EAAE;QACtB,MAAM,kBAAE,CAAC,SAAS,CAAC,eAAe,EAAE,GAAG,kBAAkB,CAAC,IAAI,EAAE,KAAK,gBAAgB,IAAI,CAAC,CAAC;KAC5F;AACH,CAAC;AAbD,wDAaC;AAEM,KAAK,UAAU,+BAA+B,CAAC,WAAmB;IACvE,MAAM,eAAe,GAAG,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAEzD,MAAM,gBAAgB,GAAG,MAAM,kBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAE5D,MAAM,kBAAkB,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,cAAI,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;IACjF,MAAM,iBAAiB,GAAG,YAAY,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IAE7E,OAAO,iBAAiB,IAAI,gBAAgB,CAAC;AAC/C,CAAC;AAVD,0EAUC","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\n\nimport gradleScript from './EasBuildGradleScript';\nimport * as Paths from './Paths';\n\nconst APPLY_EAS_GRADLE = 'apply from: \"./eas-build.gradle\"';\n\nfunction hasApplyLine(content: string, applyLine: string): boolean {\n return (\n content\n .replace(/\\r\\n/g, '\\n')\n .split('\\n')\n // Check for both single and double quotes\n .some(line => line === applyLine || line === applyLine.replace(/\"/g, \"'\"))\n );\n}\n\nexport function getEasBuildGradlePath(projectRoot: string): string {\n return path.join(projectRoot, 'android', 'app', 'eas-build.gradle');\n}\n\nexport async function configureEasBuildAsync(projectRoot: string): Promise<void> {\n const buildGradlePath = Paths.getAppBuildGradle(projectRoot);\n const easGradlePath = getEasBuildGradlePath(projectRoot);\n\n await fs.writeFile(easGradlePath, gradleScript);\n\n const buildGradleContent = await fs.readFile(path.join(buildGradlePath), 'utf8');\n\n const hasEasGradleApply = hasApplyLine(buildGradleContent, APPLY_EAS_GRADLE);\n\n if (!hasEasGradleApply) {\n await fs.writeFile(buildGradlePath, `${buildGradleContent.trim()}\\n${APPLY_EAS_GRADLE}\\n`);\n }\n}\n\nexport async function isEasBuildGradleConfiguredAsync(projectRoot: string): Promise<boolean> {\n const buildGradlePath = Paths.getAppBuildGradle(projectRoot);\n const easGradlePath = getEasBuildGradlePath(projectRoot);\n\n const hasEasGradleFile = await fs.pathExists(easGradlePath);\n\n const buildGradleContent = await fs.readFile(path.join(buildGradlePath), 'utf8');\n const hasEasGradleApply = hasApplyLine(buildGradleContent, APPLY_EAS_GRADLE);\n\n return hasEasGradleApply && hasEasGradleFile;\n}\n"]}

View File

@ -0,0 +1,2 @@
declare const _default: "// Build integration with EAS\n\nimport java.nio.file.Paths\n\nandroid {\n signingConfigs {\n release {\n // This is necessary to avoid needing the user to define a release signing config manually\n // If no release config is defined, and this is not present, build for assembleRelease will crash\n }\n }\n\n buildTypes {\n release {\n // This is necessary to avoid needing the user to define a release build type manually\n }\n }\n}\n\ndef isEasBuildConfigured = false\n\ntasks.whenTaskAdded {\n def debug = gradle.startParameter.taskNames.any { it.toLowerCase().contains('debug') }\n\n if (debug) {\n return\n }\n\n // We only need to configure EAS build once\n if (isEasBuildConfigured) {\n return\n }\n\n isEasBuildConfigured = true;\n\n android.signingConfigs.release {\n def credentialsJson = rootProject.file(\"../credentials.json\");\n\n if (credentialsJson.exists()) {\n if (storeFile && System.getenv(\"EAS_BUILD\") != \"true\") {\n println(\"Path to release keystore file is already set, ignoring 'credentials.json'\")\n } else {\n try {\n def credentials = new groovy.json.JsonSlurper().parse(credentialsJson)\n def keystorePath = Paths.get(credentials.android.keystore.keystorePath);\n def storeFilePath = keystorePath.isAbsolute()\n ? keystorePath\n : rootProject.file(\"..\").toPath().resolve(keystorePath);\n\n storeFile storeFilePath.toFile()\n storePassword credentials.android.keystore.keystorePassword\n keyAlias credentials.android.keystore.keyAlias\n keyPassword credentials.android.keystore.keyPassword\n } catch (Exception e) {\n println(\"An error occurred while parsing 'credentials.json': \" + e.message)\n }\n }\n } else {\n if (storeFile == null) {\n println(\"Couldn't find a 'credentials.json' file, skipping release keystore configuration\")\n }\n }\n }\n\n android.buildTypes.release {\n signingConfig android.signingConfigs.release\n }\n}\n";
export default _default;

View File

@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = `// Build integration with EAS
import java.nio.file.Paths
android {
signingConfigs {
release {
// This is necessary to avoid needing the user to define a release signing config manually
// If no release config is defined, and this is not present, build for assembleRelease will crash
}
}
buildTypes {
release {
// This is necessary to avoid needing the user to define a release build type manually
}
}
}
def isEasBuildConfigured = false
tasks.whenTaskAdded {
def debug = gradle.startParameter.taskNames.any { it.toLowerCase().contains('debug') }
if (debug) {
return
}
// We only need to configure EAS build once
if (isEasBuildConfigured) {
return
}
isEasBuildConfigured = true;
android.signingConfigs.release {
def credentialsJson = rootProject.file("../credentials.json");
if (credentialsJson.exists()) {
if (storeFile && System.getenv("EAS_BUILD") != "true") {
println("Path to release keystore file is already set, ignoring 'credentials.json'")
} else {
try {
def credentials = new groovy.json.JsonSlurper().parse(credentialsJson)
def keystorePath = Paths.get(credentials.android.keystore.keystorePath);
def storeFilePath = keystorePath.isAbsolute()
? keystorePath
: rootProject.file("..").toPath().resolve(keystorePath);
storeFile storeFilePath.toFile()
storePassword credentials.android.keystore.keystorePassword
keyAlias credentials.android.keystore.keyAlias
keyPassword credentials.android.keystore.keyPassword
} catch (Exception e) {
println("An error occurred while parsing 'credentials.json': " + e.message)
}
}
} else {
if (storeFile == null) {
println("Couldn't find a 'credentials.json' file, skipping release keystore configuration")
}
}
}
android.buildTypes.release {
signingConfig android.signingConfigs.release
}
}
`;
//# sourceMappingURL=EasBuildGradleScript.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"EasBuildGradleScript.js","sourceRoot":"","sources":["../../src/android/EasBuildGradleScript.ts"],"names":[],"mappings":";;AAAA,kBAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoEd,CAAC","sourcesContent":["export default `// Build integration with EAS\n\nimport java.nio.file.Paths\n\nandroid {\n signingConfigs {\n release {\n // This is necessary to avoid needing the user to define a release signing config manually\n // If no release config is defined, and this is not present, build for assembleRelease will crash\n }\n }\n\n buildTypes {\n release {\n // This is necessary to avoid needing the user to define a release build type manually\n }\n }\n}\n\ndef isEasBuildConfigured = false\n\ntasks.whenTaskAdded {\n def debug = gradle.startParameter.taskNames.any { it.toLowerCase().contains('debug') }\n\n if (debug) {\n return\n }\n\n // We only need to configure EAS build once\n if (isEasBuildConfigured) {\n return\n }\n\n isEasBuildConfigured = true;\n\n android.signingConfigs.release {\n def credentialsJson = rootProject.file(\"../credentials.json\");\n\n if (credentialsJson.exists()) {\n if (storeFile && System.getenv(\"EAS_BUILD\") != \"true\") {\n println(\"Path to release keystore file is already set, ignoring 'credentials.json'\")\n } else {\n try {\n def credentials = new groovy.json.JsonSlurper().parse(credentialsJson)\n def keystorePath = Paths.get(credentials.android.keystore.keystorePath);\n def storeFilePath = keystorePath.isAbsolute()\n ? keystorePath\n : rootProject.file(\"..\").toPath().resolve(keystorePath);\n\n storeFile storeFilePath.toFile()\n storePassword credentials.android.keystore.keystorePassword\n keyAlias credentials.android.keystore.keyAlias\n keyPassword credentials.android.keystore.keyPassword\n } catch (Exception e) {\n println(\"An error occurred while parsing 'credentials.json': \" + e.message)\n }\n }\n } else {\n if (storeFile == null) {\n println(\"Couldn't find a 'credentials.json' file, skipping release keystore configuration\")\n }\n }\n }\n\n android.buildTypes.release {\n signingConfig android.signingConfigs.release\n }\n}\n`;\n"]}

View File

@ -0,0 +1,14 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
export declare const withFacebookAppIdString: import("..").ConfigPlugin<void>;
export declare const withFacebookManifest: import("..").ConfigPlugin<void>;
declare type ExpoConfigFacebook = Pick<ExpoConfig, 'facebookScheme' | 'facebookAdvertiserIDCollectionEnabled' | 'facebookAppId' | 'facebookAutoInitEnabled' | 'facebookAutoLogAppEventsEnabled' | 'facebookDisplayName'>;
export declare function getFacebookScheme(config: ExpoConfigFacebook): string | null;
export declare function getFacebookAppId(config: ExpoConfigFacebook): string | null;
export declare function getFacebookDisplayName(config: ExpoConfigFacebook): string | null;
export declare function getFacebookAutoInitEnabled(config: ExpoConfigFacebook): boolean | null;
export declare function getFacebookAutoLogAppEvents(config: ExpoConfigFacebook): boolean | null;
export declare function getFacebookAdvertiserIDCollection(config: ExpoConfigFacebook): boolean | null;
export declare function setFacebookAppIdString(config: ExpoConfigFacebook, projectRoot: string): Promise<boolean>;
export declare function setFacebookConfig(config: ExpoConfigFacebook, androidManifest: AndroidManifest): AndroidManifest;
export {};

View File

@ -0,0 +1,171 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const XML_1 = require("../utils/XML");
const errors_1 = require("../utils/errors");
const Manifest_1 = require("./Manifest");
const Resources_1 = require("./Resources");
const Strings_1 = require("./Strings");
const CUSTOM_TAB_ACTIVITY = 'com.facebook.CustomTabActivity';
const STRING_FACEBOOK_APP_ID = 'facebook_app_id';
const META_APP_ID = 'com.facebook.sdk.ApplicationId';
const META_APP_NAME = 'com.facebook.sdk.ApplicationName';
const META_AUTO_INIT = 'com.facebook.sdk.AutoInitEnabled';
const META_AUTO_LOG_APP_EVENTS = 'com.facebook.sdk.AutoLogAppEventsEnabled';
const META_AD_ID_COLLECTION = 'com.facebook.sdk.AdvertiserIDCollectionEnabled';
exports.withFacebookAppIdString = android_plugins_1.createStringsXmlPlugin(applyFacebookAppIdString, 'withFacebookAppIdString');
exports.withFacebookManifest = android_plugins_1.createAndroidManifestPlugin(setFacebookConfig, 'withFacebookManifest');
function buildXMLItem({ head, children, }) {
return Object.assign(Object.assign({}, (children !== null && children !== void 0 ? children : {})), { $: head });
}
function buildAndroidItem(datum) {
const item = typeof datum === 'string' ? { name: datum } : datum;
const head = Manifest_1.prefixAndroidKeys(item);
return buildXMLItem({ head });
}
function getFacebookSchemeActivity(scheme) {
/**
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="${scheme}" />
</intent-filter>
</activity>
*/
return buildXMLItem({
head: Manifest_1.prefixAndroidKeys({
name: CUSTOM_TAB_ACTIVITY,
exported: 'true',
}),
children: {
'intent-filter': [
{
action: [buildAndroidItem('android.intent.action.VIEW')],
category: [
buildAndroidItem('android.intent.category.DEFAULT'),
buildAndroidItem('android.intent.category.BROWSABLE'),
],
data: [buildAndroidItem({ scheme })],
},
],
},
});
}
function getFacebookScheme(config) {
var _a;
return (_a = config.facebookScheme) !== null && _a !== void 0 ? _a : null;
}
exports.getFacebookScheme = getFacebookScheme;
function getFacebookAppId(config) {
var _a;
return (_a = config.facebookAppId) !== null && _a !== void 0 ? _a : null;
}
exports.getFacebookAppId = getFacebookAppId;
function getFacebookDisplayName(config) {
var _a;
return (_a = config.facebookDisplayName) !== null && _a !== void 0 ? _a : null;
}
exports.getFacebookDisplayName = getFacebookDisplayName;
function getFacebookAutoInitEnabled(config) {
var _a;
return (_a = config.facebookAutoInitEnabled) !== null && _a !== void 0 ? _a : null;
}
exports.getFacebookAutoInitEnabled = getFacebookAutoInitEnabled;
function getFacebookAutoLogAppEvents(config) {
var _a;
return (_a = config.facebookAutoLogAppEventsEnabled) !== null && _a !== void 0 ? _a : null;
}
exports.getFacebookAutoLogAppEvents = getFacebookAutoLogAppEvents;
function getFacebookAdvertiserIDCollection(config) {
var _a;
return (_a = config.facebookAdvertiserIDCollectionEnabled) !== null && _a !== void 0 ? _a : null;
}
exports.getFacebookAdvertiserIDCollection = getFacebookAdvertiserIDCollection;
function ensureFacebookActivity({ mainApplication, scheme, }) {
if (Array.isArray(mainApplication.activity)) {
// Remove all Facebook CustomTabActivities first
mainApplication.activity = mainApplication.activity.filter(activity => {
var _a;
return ((_a = activity.$) === null || _a === void 0 ? void 0 : _a['android:name']) !== CUSTOM_TAB_ACTIVITY;
});
}
else {
mainApplication.activity = [];
}
// If a new scheme is defined, append it to the activity.
if (scheme) {
mainApplication.activity.push(getFacebookSchemeActivity(scheme));
}
return mainApplication;
}
async function setFacebookAppIdString(config, projectRoot) {
const stringsPath = await Strings_1.getProjectStringsXMLPathAsync(projectRoot);
errors_1.assert(stringsPath, `There was a problem setting your Facebook App ID in "${stringsPath}"`);
let stringsJSON = await Resources_1.readResourcesXMLAsync({ path: stringsPath });
stringsJSON = applyFacebookAppIdString(config, stringsJSON);
try {
await XML_1.writeXMLAsync({ path: stringsPath, xml: stringsJSON });
}
catch (_a) {
throw new Error(`Error setting facebookAppId. Cannot write strings.xml to "${stringsPath}"`);
}
return true;
}
exports.setFacebookAppIdString = setFacebookAppIdString;
function applyFacebookAppIdString(config, stringsJSON) {
const appId = getFacebookAppId(config);
if (appId) {
return Strings_1.setStringItem([Resources_1.buildResourceItem({ name: STRING_FACEBOOK_APP_ID, value: appId })], stringsJSON);
}
return Strings_1.removeStringItem(STRING_FACEBOOK_APP_ID, stringsJSON);
}
function setFacebookConfig(config, androidManifest) {
const scheme = getFacebookScheme(config);
const appId = getFacebookAppId(config);
const displayName = getFacebookDisplayName(config);
const autoInitEnabled = getFacebookAutoInitEnabled(config);
const autoLogAppEvents = getFacebookAutoLogAppEvents(config);
const advertiserIdCollection = getFacebookAdvertiserIDCollection(config);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let mainApplication = Manifest_1.getMainApplicationOrThrow(androidManifest);
mainApplication = ensureFacebookActivity({ scheme, mainApplication });
if (appId) {
mainApplication = Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_APP_ID,
// The corresponding string is set in setFacebookAppIdString
`@string/${STRING_FACEBOOK_APP_ID}`);
}
else {
mainApplication = Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_APP_ID);
}
if (displayName) {
mainApplication = Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_APP_NAME, displayName);
}
else {
mainApplication = Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_APP_NAME);
}
if (autoInitEnabled !== null) {
mainApplication = Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_AUTO_INIT, autoInitEnabled ? 'true' : 'false');
}
else {
mainApplication = Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_AUTO_INIT);
}
if (autoLogAppEvents !== null) {
mainApplication = Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_AUTO_LOG_APP_EVENTS, autoLogAppEvents ? 'true' : 'false');
}
else {
mainApplication = Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_AUTO_LOG_APP_EVENTS);
}
if (advertiserIdCollection !== null) {
mainApplication = Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_AD_ID_COLLECTION, advertiserIdCollection ? 'true' : 'false');
}
else {
mainApplication = Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_AD_ID_COLLECTION);
}
return androidManifest;
}
exports.setFacebookConfig = setFacebookConfig;
//# sourceMappingURL=Facebook.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
export declare const withGoogleMapsApiKey: import("..").ConfigPlugin<void>;
export declare function getGoogleMapsApiKey(config: Pick<ExpoConfig, 'android'>): string | null;
export declare function setGoogleMapsApiKey(config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidManifest): AndroidManifest;

View File

@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const Manifest_1 = require("./Manifest");
const META_API_KEY = 'com.google.android.geo.API_KEY';
const LIB_HTTP = 'org.apache.http.legacy';
exports.withGoogleMapsApiKey = android_plugins_1.createAndroidManifestPlugin(setGoogleMapsApiKey, 'withGoogleMapsApiKey');
function getGoogleMapsApiKey(config) {
var _a, _b, _c, _d;
return (_d = (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.googleMaps) === null || _c === void 0 ? void 0 : _c.apiKey) !== null && _d !== void 0 ? _d : null;
}
exports.getGoogleMapsApiKey = getGoogleMapsApiKey;
function setGoogleMapsApiKey(config, androidManifest) {
const apiKey = getGoogleMapsApiKey(config);
const mainApplication = Manifest_1.getMainApplicationOrThrow(androidManifest);
if (apiKey) {
// If the item exists, add it back
Manifest_1.addMetaDataItemToMainApplication(mainApplication, META_API_KEY, apiKey);
Manifest_1.addUsesLibraryItemToMainApplication(mainApplication, {
name: LIB_HTTP,
required: false,
});
}
else {
// Remove any existing item
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, META_API_KEY);
Manifest_1.removeUsesLibraryItemFromMainApplication(mainApplication, LIB_HTTP);
}
return androidManifest;
}
exports.setGoogleMapsApiKey = setGoogleMapsApiKey;
//# sourceMappingURL=GoogleMapsApiKey.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"GoogleMapsApiKey.js","sourceRoot":"","sources":["../../src/android/GoogleMapsApiKey.ts"],"names":[],"mappings":";;AAEA,gEAAyE;AACzE,yCAOoB;AAEpB,MAAM,YAAY,GAAG,gCAAgC,CAAC;AACtD,MAAM,QAAQ,GAAG,wBAAwB,CAAC;AAE7B,QAAA,oBAAoB,GAAG,6CAA2B,CAC7D,mBAAmB,EACnB,sBAAsB,CACvB,CAAC;AAEF,SAAgB,mBAAmB,CAAC,MAAmC;;IACrE,+BAAO,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,UAAU,0CAAE,MAAM,mCAAI,IAAI,CAAC;AAC5D,CAAC;AAFD,kDAEC;AAED,SAAgB,mBAAmB,CACjC,MAAmC,EACnC,eAAgC;IAEhC,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,eAAe,GAAG,oCAAyB,CAAC,eAAe,CAAC,CAAC;IAEnE,IAAI,MAAM,EAAE;QACV,kCAAkC;QAClC,2CAAgC,CAAC,eAAe,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QACxE,8CAAmC,CAAC,eAAe,EAAE;YACnD,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;KACJ;SAAM;QACL,2BAA2B;QAC3B,gDAAqC,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;QACrE,mDAAwC,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;KACrE;IAED,OAAO,eAAe,CAAC;AACzB,CAAC;AArBD,kDAqBC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { createAndroidManifestPlugin } from '../plugins/android-plugins';\nimport {\n addMetaDataItemToMainApplication,\n addUsesLibraryItemToMainApplication,\n AndroidManifest,\n getMainApplicationOrThrow,\n removeMetaDataItemFromMainApplication,\n removeUsesLibraryItemFromMainApplication,\n} from './Manifest';\n\nconst META_API_KEY = 'com.google.android.geo.API_KEY';\nconst LIB_HTTP = 'org.apache.http.legacy';\n\nexport const withGoogleMapsApiKey = createAndroidManifestPlugin(\n setGoogleMapsApiKey,\n 'withGoogleMapsApiKey'\n);\n\nexport function getGoogleMapsApiKey(config: Pick<ExpoConfig, 'android'>) {\n return config.android?.config?.googleMaps?.apiKey ?? null;\n}\n\nexport function setGoogleMapsApiKey(\n config: Pick<ExpoConfig, 'android'>,\n androidManifest: AndroidManifest\n) {\n const apiKey = getGoogleMapsApiKey(config);\n const mainApplication = getMainApplicationOrThrow(androidManifest);\n\n if (apiKey) {\n // If the item exists, add it back\n addMetaDataItemToMainApplication(mainApplication, META_API_KEY, apiKey);\n addUsesLibraryItemToMainApplication(mainApplication, {\n name: LIB_HTTP,\n required: false,\n });\n } else {\n // Remove any existing item\n removeMetaDataItemFromMainApplication(mainApplication, META_API_KEY);\n removeUsesLibraryItemFromMainApplication(mainApplication, LIB_HTTP);\n }\n\n return androidManifest;\n}\n"]}

View File

@ -0,0 +1,17 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
export declare const withClassPath: ConfigPlugin;
export declare const withApplyPlugin: ConfigPlugin;
/**
* Add `google-services.json` to project
*/
export declare const withGoogleServicesFile: ConfigPlugin;
export declare function getGoogleServicesFilePath(config: Pick<ExpoConfig, 'android'>): string | null;
export declare function setGoogleServicesFile(config: Pick<ExpoConfig, 'android'>, projectRoot: string, targetPath?: string): Promise<boolean>;
/**
* Adding the Google Services plugin
* NOTE(brentvatne): string replacement is a fragile approach! we need a
* better solution than this.
*/
export declare function setClassPath(config: Pick<ExpoConfig, 'android'>, buildGradle: string): string;
export declare function applyPlugin(config: Pick<ExpoConfig, 'android'>, appBuildGradle: string): string;

View File

@ -0,0 +1,110 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = require("path");
const android_plugins_1 = require("../plugins/android-plugins");
const core_plugins_1 = require("../plugins/core-plugins");
const WarningAggregator = __importStar(require("../utils/warnings"));
const DEFAULT_TARGET_PATH = './android/app/google-services.json';
const googleServicesClassPath = 'com.google.gms:google-services';
const googleServicesPlugin = 'com.google.gms.google-services';
// NOTE(brentvatne): This may be annoying to keep up to date...
const googleServicesVersion = '4.3.3';
exports.withClassPath = config => {
return android_plugins_1.withProjectBuildGradle(config, config => {
if (config.modResults.language === 'groovy') {
config.modResults.contents = setClassPath(config, config.modResults.contents);
}
else {
WarningAggregator.addWarningAndroid('android-google-services', `Cannot automatically configure project build.gradle if it's not groovy`);
}
return config;
});
};
exports.withApplyPlugin = config => {
return android_plugins_1.withAppBuildGradle(config, config => {
if (config.modResults.language === 'groovy') {
config.modResults.contents = applyPlugin(config, config.modResults.contents);
}
else {
WarningAggregator.addWarningAndroid('android-google-services', `Cannot automatically configure app build.gradle if it's not groovy`);
}
return config;
});
};
/**
* Add `google-services.json` to project
*/
exports.withGoogleServicesFile = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setGoogleServicesFile(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getGoogleServicesFilePath(config) {
var _a, _b;
return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.googleServicesFile) !== null && _b !== void 0 ? _b : null;
}
exports.getGoogleServicesFilePath = getGoogleServicesFilePath;
async function setGoogleServicesFile(config, projectRoot, targetPath = DEFAULT_TARGET_PATH) {
const partialSourcePath = getGoogleServicesFilePath(config);
if (!partialSourcePath) {
return false;
}
const completeSourcePath = path_1.resolve(projectRoot, partialSourcePath);
const destinationPath = path_1.resolve(projectRoot, targetPath);
try {
await fs_extra_1.default.copy(completeSourcePath, destinationPath);
}
catch (e) {
throw new Error(`Cannot copy google-services.json from ${completeSourcePath} to ${destinationPath}. Please make sure the source and destination paths exist.`);
}
return true;
}
exports.setGoogleServicesFile = setGoogleServicesFile;
/**
* Adding the Google Services plugin
* NOTE(brentvatne): string replacement is a fragile approach! we need a
* better solution than this.
*/
function setClassPath(config, buildGradle) {
const googleServicesFile = getGoogleServicesFilePath(config);
if (!googleServicesFile) {
return buildGradle;
}
if (buildGradle.includes(googleServicesClassPath)) {
return buildGradle;
}
//
return buildGradle.replace(/dependencies\s?{/, `dependencies {
classpath '${googleServicesClassPath}:${googleServicesVersion}'`);
}
exports.setClassPath = setClassPath;
function applyPlugin(config, appBuildGradle) {
const googleServicesFile = getGoogleServicesFilePath(config);
if (!googleServicesFile) {
return appBuildGradle;
}
// Make sure the project does not have the plugin already
const pattern = new RegExp(`apply\\s+plugin:\\s+['"]${googleServicesPlugin}['"]`);
if (appBuildGradle.match(pattern)) {
return appBuildGradle;
}
// Add it to the end of the file
return appBuildGradle + `\napply plugin: '${googleServicesPlugin}'`;
}
exports.applyPlugin = applyPlugin;
//# sourceMappingURL=GoogleServices.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,31 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
declare type DPIString = 'mdpi' | 'hdpi' | 'xhdpi' | 'xxhdpi' | 'xxxhdpi';
declare type dpiMap = Record<DPIString, {
folderName: string;
scale: number;
}>;
export declare const dpiValues: dpiMap;
export declare const ANDROID_RES_PATH = "android/app/src/main/res/";
export declare const withIcons: ConfigPlugin;
export declare function getIcon(config: ExpoConfig): string | null;
export declare function getAdaptiveIcon(config: ExpoConfig): {
foregroundImage: string | null;
backgroundColor: string | null;
backgroundImage: string | null;
};
/**
* Resizes the user-provided icon to create a set of legacy icon files in
* their respective "mipmap" directories for <= Android 7, and creates a set of adaptive
* icon files for > Android 7 from the adaptive icon files (if provided).
*/
export declare function setIconAsync(config: ExpoConfig, projectRoot: string): Promise<true | null>;
/**
* Configures adaptive icon files to be used on Android 8 and up. A foreground image must be provided,
* and will have a transparent background unless:
* - A backgroundImage is provided, or
* - A backgroundColor was specified
*/
export declare function configureAdaptiveIconAsync(projectRoot: string, foregroundImage: string, backgroundImage: string | null, backgroundColor: string): Promise<void>;
export declare const createAdaptiveIconXmlString: (backgroundImage: string | null) => string;
export {};

213
node_modules/@expo/config-plugins/build/android/Icon.js generated vendored Normal file
View File

@ -0,0 +1,213 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const image_utils_1 = require("@expo/image-utils");
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const core_plugins_1 = require("../plugins/core-plugins");
const XML_1 = require("../utils/XML");
const Colors = __importStar(require("./Colors"));
const Resources_1 = require("./Resources");
exports.dpiValues = {
mdpi: { folderName: 'mipmap-mdpi', scale: 1 },
hdpi: { folderName: 'mipmap-hdpi', scale: 1.5 },
xhdpi: { folderName: 'mipmap-xhdpi', scale: 2 },
xxhdpi: { folderName: 'mipmap-xxhdpi', scale: 3 },
xxxhdpi: { folderName: 'mipmap-xxxhdpi', scale: 4 },
};
const BASELINE_PIXEL_SIZE = 48;
exports.ANDROID_RES_PATH = 'android/app/src/main/res/';
const MIPMAP_ANYDPI_V26 = 'mipmap-anydpi-v26';
const ICON_BACKGROUND = 'iconBackground';
const IC_LAUNCHER_PNG = 'ic_launcher.png';
const IC_LAUNCHER_ROUND_PNG = 'ic_launcher_round.png';
const IC_LAUNCHER_BACKGROUND_PNG = 'ic_launcher_background.png';
const IC_LAUNCHER_FOREGROUND_PNG = 'ic_launcher_foreground.png';
const IC_LAUNCHER_XML = 'ic_launcher.xml';
const IC_LAUNCHER_ROUND_XML = 'ic_launcher_round.xml';
exports.withIcons = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setIconAsync(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getIcon(config) {
var _a;
return config.icon || ((_a = config.android) === null || _a === void 0 ? void 0 : _a.icon) || null;
}
exports.getIcon = getIcon;
function getAdaptiveIcon(config) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
return {
foregroundImage: (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.adaptiveIcon) === null || _b === void 0 ? void 0 : _b.foregroundImage) !== null && _c !== void 0 ? _c : null,
backgroundColor: (_f = (_e = (_d = config.android) === null || _d === void 0 ? void 0 : _d.adaptiveIcon) === null || _e === void 0 ? void 0 : _e.backgroundColor) !== null && _f !== void 0 ? _f : null,
backgroundImage: (_j = (_h = (_g = config.android) === null || _g === void 0 ? void 0 : _g.adaptiveIcon) === null || _h === void 0 ? void 0 : _h.backgroundImage) !== null && _j !== void 0 ? _j : null,
};
}
exports.getAdaptiveIcon = getAdaptiveIcon;
/**
* Resizes the user-provided icon to create a set of legacy icon files in
* their respective "mipmap" directories for <= Android 7, and creates a set of adaptive
* icon files for > Android 7 from the adaptive icon files (if provided).
*/
async function setIconAsync(config, projectRoot) {
const { foregroundImage, backgroundColor, backgroundImage } = getAdaptiveIcon(config);
const icon = foregroundImage !== null && foregroundImage !== void 0 ? foregroundImage : getIcon(config);
if (!icon) {
return null;
}
await configureLegacyIconAsync(projectRoot, icon, backgroundImage, backgroundColor);
await configureAdaptiveIconAsync(projectRoot, icon, backgroundImage, backgroundColor !== null && backgroundColor !== void 0 ? backgroundColor : '#FFFFFF');
return true;
}
exports.setIconAsync = setIconAsync;
/**
* Configures legacy icon files to be used on Android 7 and earlier. If adaptive icon configuration
* was provided, we create a pseudo-adaptive icon by layering the provided files (or background
* color if no backgroundImage is provided. If no backgroundImage and no backgroundColor are provided,
* the background is set to transparent.)
*/
async function configureLegacyIconAsync(projectRoot, icon, backgroundImage, backgroundColor) {
await Promise.all(Object.values(exports.dpiValues).map(async ({ folderName, scale }) => {
const dpiFolderPath = path_1.default.resolve(projectRoot, exports.ANDROID_RES_PATH, folderName);
const iconSizePx = BASELINE_PIXEL_SIZE * scale;
// backgroundImage overrides backgroundColor
backgroundColor = backgroundImage ? 'transparent' : backgroundColor !== null && backgroundColor !== void 0 ? backgroundColor : 'transparent';
let squareIconImage = (await image_utils_1.generateImageAsync({ projectRoot, cacheType: 'android-standard-square' }, {
src: icon,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor,
})).source;
let roundIconImage = (await image_utils_1.generateImageAsync({ projectRoot, cacheType: 'android-standard-circle' }, {
src: icon,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor,
borderRadius: iconSizePx / 2,
})).source;
if (backgroundImage) {
// Layer the buffers we just created on top of the background image that's provided
const squareBackgroundLayer = (await image_utils_1.generateImageAsync({ projectRoot, cacheType: 'android-standard-square-background' }, {
src: backgroundImage,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor: 'transparent',
})).source;
const roundBackgroundLayer = (await image_utils_1.generateImageAsync({ projectRoot, cacheType: 'android-standard-round-background' }, {
src: backgroundImage,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor: 'transparent',
borderRadius: iconSizePx / 2,
})).source;
squareIconImage = await image_utils_1.compositeImagesAsync({
foreground: squareIconImage,
background: squareBackgroundLayer,
});
roundIconImage = await image_utils_1.compositeImagesAsync({
foreground: roundIconImage,
background: roundBackgroundLayer,
});
}
await fs_extra_1.default.ensureDir(dpiFolderPath);
await fs_extra_1.default.writeFile(path_1.default.resolve(dpiFolderPath, IC_LAUNCHER_PNG), squareIconImage);
await fs_extra_1.default.writeFile(path_1.default.resolve(dpiFolderPath, IC_LAUNCHER_ROUND_PNG), roundIconImage);
}));
}
/**
* Configures adaptive icon files to be used on Android 8 and up. A foreground image must be provided,
* and will have a transparent background unless:
* - A backgroundImage is provided, or
* - A backgroundColor was specified
*/
async function configureAdaptiveIconAsync(projectRoot, foregroundImage, backgroundImage, backgroundColor) {
await setBackgroundColorAsync(projectRoot, backgroundColor);
await Promise.all(Object.values(exports.dpiValues).map(async ({ folderName, scale }) => {
const dpiFolderPath = path_1.default.resolve(projectRoot, exports.ANDROID_RES_PATH, folderName);
const iconSizePx = BASELINE_PIXEL_SIZE * scale;
try {
const adpativeIconForeground = (await image_utils_1.generateImageAsync({ projectRoot, cacheType: 'android-adaptive-foreground' }, {
src: foregroundImage,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor: 'transparent',
})).source;
await fs_extra_1.default.writeFile(path_1.default.resolve(dpiFolderPath, IC_LAUNCHER_FOREGROUND_PNG), adpativeIconForeground);
if (backgroundImage) {
const adpativeIconBackground = (await image_utils_1.generateImageAsync({ projectRoot, cacheType: 'android-adaptive-background' }, {
src: backgroundImage,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor: 'transparent',
})).source;
await fs_extra_1.default.writeFile(path_1.default.resolve(dpiFolderPath, IC_LAUNCHER_BACKGROUND_PNG), adpativeIconBackground);
}
else {
// Remove any instances of ic_launcher_background.png that are there from previous icons
await removeBackgroundImageFilesAsync(projectRoot);
}
}
catch (e) {
throw new Error('Encountered an issue resizing adaptive app icon: ' + e);
}
}));
// create ic_launcher.xml and ic_launcher_round.xml
const icLauncherXmlString = exports.createAdaptiveIconXmlString(backgroundImage);
await createAdaptiveIconXmlFiles(projectRoot, icLauncherXmlString);
}
exports.configureAdaptiveIconAsync = configureAdaptiveIconAsync;
async function setBackgroundColorAsync(projectRoot, backgroundColor) {
const colorsXmlPath = await Colors.getProjectColorsXMLPathAsync(projectRoot);
let colorsJson = await Resources_1.readResourcesXMLAsync({ path: colorsXmlPath });
if (backgroundColor) {
const colorItemToAdd = Resources_1.buildResourceItem({ name: ICON_BACKGROUND, value: backgroundColor });
colorsJson = Colors.setColorItem(colorItemToAdd, colorsJson);
}
else {
colorsJson = Colors.removeColorItem(ICON_BACKGROUND, colorsJson);
}
await XML_1.writeXMLAsync({ path: colorsXmlPath, xml: colorsJson });
}
exports.createAdaptiveIconXmlString = (backgroundImage) => {
let background = `<background android:drawable="@color/iconBackground"/>`;
if (backgroundImage) {
background = `<background android:drawable="@mipmap/ic_launcher_background"/>`;
}
return `<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
${background}
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>`;
};
async function createAdaptiveIconXmlFiles(projectRoot, icLauncherXmlString) {
const anyDpiV26Directory = path_1.default.resolve(projectRoot, exports.ANDROID_RES_PATH, MIPMAP_ANYDPI_V26);
await fs_extra_1.default.ensureDir(anyDpiV26Directory);
await fs_extra_1.default.writeFile(path_1.default.resolve(anyDpiV26Directory, IC_LAUNCHER_XML), icLauncherXmlString);
await fs_extra_1.default.writeFile(path_1.default.resolve(anyDpiV26Directory, IC_LAUNCHER_ROUND_XML), icLauncherXmlString);
}
async function removeBackgroundImageFilesAsync(projectRoot) {
return await Promise.all(Object.values(exports.dpiValues).map(async ({ folderName }) => {
const dpiFolderPath = path_1.default.resolve(projectRoot, exports.ANDROID_RES_PATH, folderName);
await fs_extra_1.default.remove(path_1.default.resolve(dpiFolderPath, IC_LAUNCHER_BACKGROUND_PNG));
}));
}
//# sourceMappingURL=Icon.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
import { Android, ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
declare type AndroidIntentFilters = NonNullable<Android['intentFilters']>;
export declare const withAndroidIntentFilters: import("..").ConfigPlugin<void>;
export declare function getIntentFilters(config: Pick<ExpoConfig, 'android'>): AndroidIntentFilters;
export declare function setAndroidIntentFilters(config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidManifest): Promise<AndroidManifest>;
export default function renderIntentFilters(intentFilters: AndroidIntentFilters): string[];
export {};

View File

@ -0,0 +1,70 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const xml2js_1 = require("xml2js");
const android_plugins_1 = require("../plugins/android-plugins");
const Manifest_1 = require("./Manifest");
// TODO: make it so intent filters aren't written again if you run the command again
exports.withAndroidIntentFilters = android_plugins_1.createAndroidManifestPlugin(setAndroidIntentFilters, 'withAndroidIntentFilters');
function getIntentFilters(config) {
var _a, _b;
return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.intentFilters) !== null && _b !== void 0 ? _b : [];
}
exports.getIntentFilters = getIntentFilters;
async function setAndroidIntentFilters(config, androidManifest) {
var _a;
const intentFilters = getIntentFilters(config);
if (!intentFilters.length) {
return androidManifest;
}
const intentFiltersXML = renderIntentFilters(intentFilters).join('');
const parser = new xml2js_1.Parser();
const intentFiltersJSON = await parser.parseStringPromise(intentFiltersXML);
const mainActivity = Manifest_1.getMainActivityOrThrow(androidManifest);
mainActivity['intent-filter'] = (_a = mainActivity['intent-filter']) === null || _a === void 0 ? void 0 : _a.concat(intentFiltersJSON['intent-filter']);
return androidManifest;
}
exports.setAndroidIntentFilters = setAndroidIntentFilters;
function renderIntentFilters(intentFilters) {
// returns an array of <intent-filter> tags:
// [
// `<intent-filter>
// <data android:scheme="exp"/>
// <data android:scheme="exps"/>
//
// <action android:name="android.intent.action.VIEW"/>
//
// <category android:name="android.intent.category.DEFAULT"/>
// <category android:name="android.intent.category.BROWSABLE"/>
// </intent-filter>`,
// ...
// ]
return intentFilters.map(intentFilter => {
const autoVerify = intentFilter.autoVerify ? ' android:autoVerify="true"' : '';
return `<intent-filter${autoVerify}>
${renderIntentFilterData(intentFilter.data)}
<action android:name="android.intent.action.${intentFilter.action}"/>
${renderIntentFilterCategory(intentFilter.category)}
</intent-filter>`;
});
}
exports.default = renderIntentFilters;
function renderIntentFilterDatumEntries(datum = {}) {
const entries = [];
for (const [key, value] of Object.entries(datum)) {
entries.push(`android:${key}="${value}"`);
}
return entries.join(' ');
}
function renderIntentFilterData(data) {
return (Array.isArray(data) ? data : [data])
.filter(Boolean)
.map(datum => `<data ${renderIntentFilterDatumEntries(datum)}/>`)
.join('\n');
}
function renderIntentFilterCategory(category) {
return (Array.isArray(category) ? category : [category])
.filter(Boolean)
.map(cat => `<category android:name="android.intent.category.${cat}"/>`)
.join('\n');
}
//# sourceMappingURL=IntentFilters.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,124 @@
export declare type StringBoolean = 'true' | 'false';
declare type ManifestMetaDataAttributes = AndroidManifestAttributes & {
'android:value'?: string;
'android:resource'?: string;
};
declare type AndroidManifestAttributes = {
'android:name': string | 'android.intent.action.VIEW';
};
declare type ManifestAction = {
$: AndroidManifestAttributes;
};
declare type ManifestCategory = {
$: AndroidManifestAttributes;
};
declare type ManifestData = {
$: {
[key: string]: string | undefined;
'android:host'?: string;
'android:pathPrefix'?: string;
'android:scheme'?: string;
};
};
declare type ManifestReciever = {
$: AndroidManifestAttributes & {
'android:exported'?: StringBoolean;
'android:enabled'?: StringBoolean;
};
'intent-filter'?: ManifestIntentFilter[];
};
declare type ManifestIntentFilter = {
action?: ManifestAction[];
data?: ManifestData[];
category?: ManifestCategory[];
};
export declare type ManifestMetaData = {
$: ManifestMetaDataAttributes;
};
declare type ManifestServiceAttributes = AndroidManifestAttributes & {
'android:enabled'?: StringBoolean;
'android:exported'?: StringBoolean;
'android:permission'?: string;
};
declare type ManifestService = {
$: ManifestServiceAttributes;
'intent-filter'?: ManifestIntentFilter[];
};
declare type ManifestApplicationAttributes = {
'android:name': string | '.MainApplication';
'android:icon'?: string;
'android:label'?: string;
'android:allowBackup'?: StringBoolean;
'android:largeHeap'?: StringBoolean;
'android:requestLegacyExternalStorage'?: StringBoolean;
'android:usesCleartextTraffic'?: StringBoolean;
[key: string]: string | undefined;
};
export declare type ManifestActivity = {
$: ManifestApplicationAttributes & {
'android:exported'?: StringBoolean;
'android:launchMode'?: string;
'android:theme'?: string;
[key: string]: string | undefined;
};
'intent-filter'?: ManifestIntentFilter[];
};
export declare type ManifestUsesLibrary = {
$: AndroidManifestAttributes & {
'android:required'?: StringBoolean;
};
};
export declare type ManifestApplication = {
$: ManifestApplicationAttributes;
activity?: ManifestActivity[];
service?: ManifestService[];
receiver?: ManifestReciever[];
'meta-data'?: ManifestMetaData[];
'uses-library'?: ManifestUsesLibrary[];
};
declare type ManifestPermission = {
$: AndroidManifestAttributes & {
'android:protectionLevel'?: string | 'signature';
};
};
export declare type ManifestUsesPermission = {
$: AndroidManifestAttributes;
};
declare type ManifestUsesFeature = {
$: AndroidManifestAttributes & {
'android:glEsVersion'?: string;
'android:required': StringBoolean;
};
};
export declare type AndroidManifest = {
manifest: {
$: {
'xmlns:android': string;
package?: string;
[key: string]: string | undefined;
};
permission?: ManifestPermission[];
'uses-permission'?: ManifestUsesPermission[];
'uses-permission-sdk-23'?: ManifestUsesPermission[];
'uses-feature'?: ManifestUsesFeature[];
application?: ManifestApplication[];
};
};
export declare function writeAndroidManifestAsync(manifestPath: string, androidManifest: AndroidManifest): Promise<void>;
export declare function readAndroidManifestAsync(manifestPath: string): Promise<AndroidManifest>;
export declare function getMainApplication(androidManifest: AndroidManifest): ManifestApplication | null;
export declare function getMainApplicationOrThrow(androidManifest: AndroidManifest): ManifestApplication;
export declare function getMainActivityOrThrow(androidManifest: AndroidManifest): ManifestActivity;
export declare function getMainActivity(androidManifest: AndroidManifest): ManifestActivity | null;
export declare function addMetaDataItemToMainApplication(mainApplication: ManifestApplication, itemName: string, itemValue: string, itemType?: 'resource' | 'value'): ManifestApplication;
export declare function removeMetaDataItemFromMainApplication(mainApplication: any, itemName: string): any;
export declare function findMetaDataItem(mainApplication: any, itemName: string): number;
export declare function findUsesLibraryItem(mainApplication: any, itemName: string): number;
export declare function getMainApplicationMetaDataValue(androidManifest: AndroidManifest, name: string): string | null;
export declare function addUsesLibraryItemToMainApplication(mainApplication: ManifestApplication, item: {
name: string;
required?: boolean;
}): ManifestApplication;
export declare function removeUsesLibraryItemFromMainApplication(mainApplication: ManifestApplication, itemName: string): ManifestApplication;
export declare function prefixAndroidKeys<T extends Record<string, any> = Record<string, string>>(head: T): Record<string, any>;
export {};

View File

@ -0,0 +1,145 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const XML = __importStar(require("../utils/XML"));
const errors_1 = require("../utils/errors");
async function writeAndroidManifestAsync(manifestPath, androidManifest) {
const manifestXml = XML.format(androidManifest);
await fs_extra_1.default.ensureDir(path_1.default.dirname(manifestPath));
await fs_extra_1.default.writeFile(manifestPath, manifestXml);
}
exports.writeAndroidManifestAsync = writeAndroidManifestAsync;
async function readAndroidManifestAsync(manifestPath) {
const xml = await XML.readXMLAsync({ path: manifestPath });
if (!isManifest(xml)) {
throw new Error('Invalid manifest found at: ' + manifestPath);
}
return xml;
}
exports.readAndroidManifestAsync = readAndroidManifestAsync;
function isManifest(xml) {
// TODO: Maybe more validation
return !!xml.manifest;
}
function getMainApplication(androidManifest) {
var _a, _b, _c;
return ((_c = (_b = (_a = androidManifest === null || androidManifest === void 0 ? void 0 : androidManifest.manifest) === null || _a === void 0 ? void 0 : _a.application) === null || _b === void 0 ? void 0 : _b.filter(e => { var _a; return ((_a = e === null || e === void 0 ? void 0 : e.$) === null || _a === void 0 ? void 0 : _a['android:name']) === '.MainApplication'; })[0]) !== null && _c !== void 0 ? _c : null);
}
exports.getMainApplication = getMainApplication;
function getMainApplicationOrThrow(androidManifest) {
const mainApplication = getMainApplication(androidManifest);
errors_1.assert(mainApplication, 'AndroidManifest.xml is missing the required MainApplication element');
return mainApplication;
}
exports.getMainApplicationOrThrow = getMainApplicationOrThrow;
function getMainActivityOrThrow(androidManifest) {
const mainActivity = getMainActivity(androidManifest);
errors_1.assert(mainActivity, 'AndroidManifest.xml is missing the required MainActivity element');
return mainActivity;
}
exports.getMainActivityOrThrow = getMainActivityOrThrow;
function getMainActivity(androidManifest) {
var _a, _b, _c, _d, _e, _f;
const mainActivity = (_e = (_d = (_c = (_b = (_a = androidManifest === null || androidManifest === void 0 ? void 0 : androidManifest.manifest) === null || _a === void 0 ? void 0 : _a.application) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.activity) === null || _d === void 0 ? void 0 : _d.filter) === null || _e === void 0 ? void 0 : _e.call(_d, (e) => e.$['android:name'] === '.MainActivity');
return (_f = mainActivity === null || mainActivity === void 0 ? void 0 : mainActivity[0]) !== null && _f !== void 0 ? _f : null;
}
exports.getMainActivity = getMainActivity;
function addMetaDataItemToMainApplication(mainApplication, itemName, itemValue, itemType = 'value') {
let existingMetaDataItem;
const newItem = {
$: prefixAndroidKeys({ name: itemName, [itemType]: itemValue }),
};
if (mainApplication['meta-data']) {
existingMetaDataItem = mainApplication['meta-data'].filter((e) => e.$['android:name'] === itemName);
if (existingMetaDataItem.length) {
existingMetaDataItem[0].$[`android:${itemType}`] = itemValue;
}
else {
mainApplication['meta-data'].push(newItem);
}
}
else {
mainApplication['meta-data'] = [newItem];
}
return mainApplication;
}
exports.addMetaDataItemToMainApplication = addMetaDataItemToMainApplication;
function removeMetaDataItemFromMainApplication(mainApplication, itemName) {
const index = findMetaDataItem(mainApplication, itemName);
if ((mainApplication === null || mainApplication === void 0 ? void 0 : mainApplication['meta-data']) && index > -1) {
mainApplication['meta-data'].splice(index, 1);
}
return mainApplication;
}
exports.removeMetaDataItemFromMainApplication = removeMetaDataItemFromMainApplication;
function findApplicationSubItem(mainApplication, category, itemName) {
const parent = mainApplication[category];
if (Array.isArray(parent)) {
const index = parent.findIndex((e) => e.$['android:name'] === itemName);
return index;
}
return -1;
}
function findMetaDataItem(mainApplication, itemName) {
return findApplicationSubItem(mainApplication, 'meta-data', itemName);
}
exports.findMetaDataItem = findMetaDataItem;
function findUsesLibraryItem(mainApplication, itemName) {
return findApplicationSubItem(mainApplication, 'uses-library', itemName);
}
exports.findUsesLibraryItem = findUsesLibraryItem;
function getMainApplicationMetaDataValue(androidManifest, name) {
var _a, _b;
const mainApplication = getMainApplication(androidManifest);
if (mainApplication === null || mainApplication === void 0 ? void 0 : mainApplication.hasOwnProperty('meta-data')) {
const item = (_a = mainApplication === null || mainApplication === void 0 ? void 0 : mainApplication['meta-data']) === null || _a === void 0 ? void 0 : _a.find((e) => e.$['android:name'] === name);
return (_b = item === null || item === void 0 ? void 0 : item.$['android:value']) !== null && _b !== void 0 ? _b : null;
}
return null;
}
exports.getMainApplicationMetaDataValue = getMainApplicationMetaDataValue;
function addUsesLibraryItemToMainApplication(mainApplication, item) {
let existingMetaDataItem;
const newItem = {
$: prefixAndroidKeys(item),
};
if (mainApplication['uses-library']) {
existingMetaDataItem = mainApplication['uses-library'].filter(e => e.$['android:name'] === item.name);
if (existingMetaDataItem.length) {
existingMetaDataItem[0].$ = newItem.$;
}
else {
mainApplication['uses-library'].push(newItem);
}
}
else {
mainApplication['uses-library'] = [newItem];
}
return mainApplication;
}
exports.addUsesLibraryItemToMainApplication = addUsesLibraryItemToMainApplication;
function removeUsesLibraryItemFromMainApplication(mainApplication, itemName) {
const index = findUsesLibraryItem(mainApplication, itemName);
if ((mainApplication === null || mainApplication === void 0 ? void 0 : mainApplication['uses-library']) && index > -1) {
mainApplication['uses-library'].splice(index, 1);
}
return mainApplication;
}
exports.removeUsesLibraryItemFromMainApplication = removeUsesLibraryItemFromMainApplication;
function prefixAndroidKeys(head) {
// prefix all keys with `android:`
return Object.entries(head).reduce((prev, [key, curr]) => (Object.assign(Object.assign({}, prev), { [`android:${key}`]: curr })), {});
}
exports.prefixAndroidKeys = prefixAndroidKeys;
//# sourceMappingURL=Manifest.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,24 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
/**
* Sanitize a name, this should be used for files and gradle names.
* - `[/, \, :, <, >, ", ?, *, |]` are not allowed https://bit.ly/3l6xqKL
*
* @param name
*/
export declare function sanitizeNameForGradle(name: string): string;
export declare const withName: ConfigPlugin<void>;
export declare const withNameSettingsGradle: ConfigPlugin;
export declare function getName(config: Pick<ExpoConfig, 'name'>): string | null;
/**
* Changes the display name on the home screen,
* notifications, and others.
*/
export declare function setName(config: Pick<ExpoConfig, 'name'>, projectRoot: string): Promise<boolean>;
/**
* Regex a name change -- fragile.
*
* @param config
* @param settingsGradle
*/
export declare function applyNameSettingsGradle(config: Pick<ExpoConfig, 'name'>, settingsGradle: string): string;

View File

@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const XML_1 = require("../utils/XML");
const errors_1 = require("../utils/errors");
const warnings_1 = require("../utils/warnings");
const Resources_1 = require("./Resources");
const Strings_1 = require("./Strings");
/**
* Sanitize a name, this should be used for files and gradle names.
* - `[/, \, :, <, >, ", ?, *, |]` are not allowed https://bit.ly/3l6xqKL
*
* @param name
*/
function sanitizeNameForGradle(name) {
// Gradle disallows these:
// The project name 'My-Special 😃 Co/ol_Project' must not contain any of the following characters: [/, \, :, <, >, ", ?, *, |]. Set the 'rootProject.name' or adjust the 'include' statement (see https://docs.gradle.org/6.2/dsl/org.gradle.api.initialization.Settings.html#org.gradle.api.initialization.Settings:include(java.lang.String[]) for more details).
return name.replace(/(\/|\\|:|<|>|"|\?|\*|\|)/g, '');
}
exports.sanitizeNameForGradle = sanitizeNameForGradle;
exports.withName = android_plugins_1.createStringsXmlPlugin(applyNameFromConfig, 'withName');
exports.withNameSettingsGradle = config => {
return android_plugins_1.withSettingsGradle(config, config => {
if (config.modResults.language === 'groovy') {
config.modResults.contents = applyNameSettingsGradle(config, config.modResults.contents);
}
else {
warnings_1.addWarningAndroid('android-name-settings-gradle', `Cannot automatically configure settings.gradle if it's not groovy`);
}
return config;
});
};
function getName(config) {
return typeof config.name === 'string' ? config.name : null;
}
exports.getName = getName;
/**
* Changes the display name on the home screen,
* notifications, and others.
*/
async function setName(config, projectRoot) {
const stringsPath = await Strings_1.getProjectStringsXMLPathAsync(projectRoot);
errors_1.assert(stringsPath);
let stringsJSON = await Resources_1.readResourcesXMLAsync({ path: stringsPath });
stringsJSON = applyNameFromConfig(config, stringsJSON);
try {
await XML_1.writeXMLAsync({ path: stringsPath, xml: stringsJSON });
}
catch (_a) {
throw new Error(`Error setting name. Cannot write strings.xml to ${stringsPath}.`);
}
return true;
}
exports.setName = setName;
function applyNameFromConfig(config, stringsJSON) {
const name = getName(config);
if (name) {
return Strings_1.setStringItem([Resources_1.buildResourceItem({ name: 'app_name', value: name })], stringsJSON);
}
return Strings_1.removeStringItem('app_name', stringsJSON);
}
/**
* Regex a name change -- fragile.
*
* @param config
* @param settingsGradle
*/
function applyNameSettingsGradle(config, settingsGradle) {
var _a;
const name = sanitizeNameForGradle((_a = getName(config)) !== null && _a !== void 0 ? _a : '');
// Select rootProject.name = '***' and replace the contents between the quotes.
return settingsGradle.replace(/rootProject.name\s?=\s?(["'])(?:(?=(\\?))\2.)*?\1/g, `rootProject.name = '${name}'`);
}
exports.applyNameSettingsGradle = applyNameSettingsGradle;
//# sourceMappingURL=Name.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
export declare const withNavigationBar: ConfigPlugin;
export declare function getNavigationBarImmersiveMode(config: Pick<ExpoConfig, 'androidNavigationBar'>): "leanback" | "immersive" | "sticky-immersive" | null;
export declare function getNavigationBarColor(config: Pick<ExpoConfig, 'androidNavigationBar'>): string | null;
export declare function getNavigationBarStyle(config: Pick<ExpoConfig, 'androidNavigationBar'>): "light-content" | "dark-content";
export declare function setNavigationBarConfig(config: Pick<ExpoConfig, 'androidNavigationBar'>, projectRoot: string): Promise<boolean>;

View File

@ -0,0 +1,90 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_plugins_1 = require("../plugins/core-plugins");
const XML_1 = require("../utils/XML");
const WarningAggregator = __importStar(require("../utils/warnings"));
const Colors_1 = require("./Colors");
const Resources_1 = require("./Resources");
const Styles_1 = require("./Styles");
const NAVIGATION_BAR_COLOR = 'navigationBarColor';
const WINDOW_LIGHT_NAVIGATION_BAR = 'android:windowLightNavigationBar';
exports.withNavigationBar = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setNavigationBarConfig(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getNavigationBarImmersiveMode(config) {
var _a;
return ((_a = config.androidNavigationBar) === null || _a === void 0 ? void 0 : _a.visible) || null;
}
exports.getNavigationBarImmersiveMode = getNavigationBarImmersiveMode;
function getNavigationBarColor(config) {
var _a;
return ((_a = config.androidNavigationBar) === null || _a === void 0 ? void 0 : _a.backgroundColor) || null;
}
exports.getNavigationBarColor = getNavigationBarColor;
function getNavigationBarStyle(config) {
var _a;
return ((_a = config.androidNavigationBar) === null || _a === void 0 ? void 0 : _a.barStyle) || 'light-content';
}
exports.getNavigationBarStyle = getNavigationBarStyle;
async function setNavigationBarConfig(config, projectRoot) {
const immersiveMode = getNavigationBarImmersiveMode(config);
const hexString = getNavigationBarColor(config);
const barStyle = getNavigationBarStyle(config);
const stylesPath = await Styles_1.getProjectStylesXMLPathAsync(projectRoot);
const colorsPath = await Colors_1.getProjectColorsXMLPathAsync(projectRoot);
let stylesJSON = await Resources_1.readResourcesXMLAsync({ path: stylesPath });
let colorsJSON = await Resources_1.readResourcesXMLAsync({ path: colorsPath });
if (immersiveMode) {
// Immersive mode needs to be set programatically
WarningAggregator.addWarningAndroid('androidNavigationBar.visible', 'Hiding the navigation bar must be done programmatically. Refer to the Android documentation - https://developer.android.com/training/system-ui/immersive - for instructions.');
}
if (hexString) {
const colorItemToAdd = Resources_1.buildResourceItem({ name: NAVIGATION_BAR_COLOR, value: hexString });
colorsJSON = Colors_1.setColorItem(colorItemToAdd, colorsJSON);
const styleItemToAdd = Resources_1.buildResourceItem({
name: `android:${NAVIGATION_BAR_COLOR}`,
value: `@color/${NAVIGATION_BAR_COLOR}`,
});
stylesJSON = Styles_1.setStylesItem({
item: styleItemToAdd,
xml: stylesJSON,
parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },
});
}
if (barStyle === 'dark-content') {
const navigationBarStyleItem = Resources_1.buildResourceItem({
name: WINDOW_LIGHT_NAVIGATION_BAR,
value: 'true',
});
stylesJSON = Styles_1.setStylesItem({
item: navigationBarStyleItem,
xml: stylesJSON,
parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },
});
}
try {
await Promise.all([
XML_1.writeXMLAsync({ path: colorsPath, xml: colorsJSON }),
XML_1.writeXMLAsync({ path: stylesPath, xml: stylesJSON }),
]);
}
catch (e) {
throw new Error(`Error setting Android navigation bar color. Cannot write colors.xml to ${colorsPath}, or styles.xml to ${stylesPath}.`);
}
return true;
}
exports.setNavigationBarConfig = setNavigationBarConfig;
//# sourceMappingURL=NavigationBar.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,21 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
import { AndroidManifest } from './Manifest';
export declare const META_DATA_NOTIFICATION_ICON = "expo.modules.notifications.default_notification_icon";
export declare const META_DATA_NOTIFICATION_ICON_COLOR = "expo.modules.notifications.default_notification_color";
export declare const NOTIFICATION_ICON = "notification_icon";
export declare const NOTIFICATION_ICON_RESOURCE: string;
export declare const NOTIFICATION_ICON_COLOR = "notification_icon_color";
export declare const NOTIFICATION_ICON_COLOR_RESOURCE: string;
export declare const withNotificationIcons: ConfigPlugin;
export declare const withNotificationIconColor: ConfigPlugin;
export declare const withNotificationManifest: ConfigPlugin<void>;
export declare function getNotificationIcon(config: ExpoConfig): string | null;
export declare function getNotificationColor(config: ExpoConfig): string | null;
/**
* Applies configuration for expo-notifications, including
* the notification icon and notification color.
*/
export declare function setNotificationIconAsync(config: ExpoConfig, projectRoot: string): Promise<void>;
export declare function setNotificationConfigAsync(config: ExpoConfig, manifest: AndroidManifest): Promise<AndroidManifest>;
export declare function setNotificationIconColorAsync(config: ExpoConfig, projectRoot: string): Promise<void>;

View File

@ -0,0 +1,134 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const image_utils_1 = require("@expo/image-utils");
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const android_plugins_1 = require("../plugins/android-plugins");
const core_plugins_1 = require("../plugins/core-plugins");
const XML_1 = require("../utils/XML");
const Colors = __importStar(require("./Colors"));
const Icon_1 = require("./Icon");
const Manifest_1 = require("./Manifest");
const Resources_1 = require("./Resources");
const BASELINE_PIXEL_SIZE = 24;
exports.META_DATA_NOTIFICATION_ICON = 'expo.modules.notifications.default_notification_icon';
exports.META_DATA_NOTIFICATION_ICON_COLOR = 'expo.modules.notifications.default_notification_color';
exports.NOTIFICATION_ICON = 'notification_icon';
exports.NOTIFICATION_ICON_RESOURCE = `@drawable/${exports.NOTIFICATION_ICON}`;
exports.NOTIFICATION_ICON_COLOR = 'notification_icon_color';
exports.NOTIFICATION_ICON_COLOR_RESOURCE = `@color/${exports.NOTIFICATION_ICON_COLOR}`;
exports.withNotificationIcons = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setNotificationIconAsync(config, config.modRequest.projectRoot);
return config;
},
]);
};
exports.withNotificationIconColor = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setNotificationIconColorAsync(config, config.modRequest.projectRoot);
return config;
},
]);
};
exports.withNotificationManifest = android_plugins_1.createAndroidManifestPlugin(setNotificationConfigAsync, 'withNotificationManifest');
function getNotificationIcon(config) {
var _a;
return ((_a = config.notification) === null || _a === void 0 ? void 0 : _a.icon) || null;
}
exports.getNotificationIcon = getNotificationIcon;
function getNotificationColor(config) {
var _a;
return ((_a = config.notification) === null || _a === void 0 ? void 0 : _a.color) || null;
}
exports.getNotificationColor = getNotificationColor;
/**
* Applies configuration for expo-notifications, including
* the notification icon and notification color.
*/
async function setNotificationIconAsync(config, projectRoot) {
const icon = getNotificationIcon(config);
if (icon) {
await writeNotificationIconImageFilesAsync(icon, projectRoot);
}
else {
await removeNotificationIconImageFilesAsync(projectRoot);
}
}
exports.setNotificationIconAsync = setNotificationIconAsync;
async function setNotificationConfigAsync(config, manifest) {
const icon = getNotificationIcon(config);
const color = getNotificationColor(config);
const mainApplication = Manifest_1.getMainApplicationOrThrow(manifest);
if (icon) {
Manifest_1.addMetaDataItemToMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON, exports.NOTIFICATION_ICON_RESOURCE, 'resource');
}
else {
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON);
}
if (color) {
Manifest_1.addMetaDataItemToMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON_COLOR, exports.NOTIFICATION_ICON_COLOR_RESOURCE, 'resource');
}
else {
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, exports.META_DATA_NOTIFICATION_ICON_COLOR);
}
return manifest;
}
exports.setNotificationConfigAsync = setNotificationConfigAsync;
async function setNotificationIconColorAsync(config, projectRoot) {
const color = getNotificationColor(config);
const colorsXmlPath = await Colors.getProjectColorsXMLPathAsync(projectRoot);
let colorsJson = await Resources_1.readResourcesXMLAsync({ path: colorsXmlPath });
if (color) {
const colorItemToAdd = Resources_1.buildResourceItem({ name: exports.NOTIFICATION_ICON_COLOR, value: color });
colorsJson = Colors.setColorItem(colorItemToAdd, colorsJson);
}
else {
colorsJson = Colors.removeColorItem(exports.NOTIFICATION_ICON_COLOR, colorsJson);
}
await XML_1.writeXMLAsync({ path: colorsXmlPath, xml: colorsJson });
}
exports.setNotificationIconColorAsync = setNotificationIconColorAsync;
async function writeNotificationIconImageFilesAsync(icon, projectRoot) {
await Promise.all(Object.values(Icon_1.dpiValues).map(async ({ folderName, scale }) => {
const drawableFolderName = folderName.replace('mipmap', 'drawable');
const dpiFolderPath = path_1.default.resolve(projectRoot, Icon_1.ANDROID_RES_PATH, drawableFolderName);
await fs_extra_1.default.ensureDir(dpiFolderPath);
const iconSizePx = BASELINE_PIXEL_SIZE * scale;
try {
const resizedIcon = (await image_utils_1.generateImageAsync({ projectRoot, cacheType: 'android-notification' }, {
src: icon,
width: iconSizePx,
height: iconSizePx,
resizeMode: 'cover',
backgroundColor: 'transparent',
})).source;
await fs_extra_1.default.writeFile(path_1.default.resolve(dpiFolderPath, exports.NOTIFICATION_ICON + '.png'), resizedIcon);
}
catch (e) {
throw new Error('Encountered an issue resizing Android notification icon: ' + e);
}
}));
}
async function removeNotificationIconImageFilesAsync(projectRoot) {
await Promise.all(Object.values(Icon_1.dpiValues).map(async ({ folderName }) => {
const drawableFolderName = folderName.replace('mipmap', 'drawable');
const dpiFolderPath = path_1.default.resolve(projectRoot, Icon_1.ANDROID_RES_PATH, drawableFolderName);
await fs_extra_1.default.remove(path_1.default.resolve(dpiFolderPath, exports.NOTIFICATION_ICON + '.png'));
}));
}
//# sourceMappingURL=Notifications.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,6 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
export declare const SCREEN_ORIENTATION_ATTRIBUTE = "android:screenOrientation";
export declare const withOrientation: import("..").ConfigPlugin<void>;
export declare function getOrientation(config: Pick<ExpoConfig, 'orientation'>): "default" | "portrait" | "landscape" | null;
export declare function setAndroidOrientation(config: Pick<ExpoConfig, 'orientation'>, androidManifest: AndroidManifest): AndroidManifest;

View File

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const Manifest_1 = require("./Manifest");
exports.SCREEN_ORIENTATION_ATTRIBUTE = 'android:screenOrientation';
exports.withOrientation = android_plugins_1.createAndroidManifestPlugin(setAndroidOrientation, 'withOrientation');
function getOrientation(config) {
return typeof config.orientation === 'string' ? config.orientation : null;
}
exports.getOrientation = getOrientation;
function setAndroidOrientation(config, androidManifest) {
const orientation = getOrientation(config);
// TODO: Remove this if we decide to remove any orientation configuration when not specified
if (!orientation) {
return androidManifest;
}
const mainActivity = Manifest_1.getMainActivityOrThrow(androidManifest);
mainActivity.$[exports.SCREEN_ORIENTATION_ATTRIBUTE] =
orientation !== 'default' ? orientation : 'unspecified';
return androidManifest;
}
exports.setAndroidOrientation = setAndroidOrientation;
//# sourceMappingURL=Orientation.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Orientation.js","sourceRoot":"","sources":["../../src/android/Orientation.ts"],"names":[],"mappings":";;AAEA,gEAAyE;AACzE,yCAAqE;AAExD,QAAA,4BAA4B,GAAG,2BAA2B,CAAC;AAE3D,QAAA,eAAe,GAAG,6CAA2B,CACxD,qBAAqB,EACrB,iBAAiB,CAClB,CAAC;AAEF,SAAgB,cAAc,CAAC,MAAuC;IACpE,OAAO,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5E,CAAC;AAFD,wCAEC;AAED,SAAgB,qBAAqB,CACnC,MAAuC,EACvC,eAAgC;IAEhC,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,4FAA4F;IAC5F,IAAI,CAAC,WAAW,EAAE;QAChB,OAAO,eAAe,CAAC;KACxB;IAED,MAAM,YAAY,GAAG,iCAAsB,CAAC,eAAe,CAAC,CAAC;IAE7D,YAAY,CAAC,CAAC,CAAC,oCAA4B,CAAC;QAC1C,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;IAE1D,OAAO,eAAe,CAAC;AACzB,CAAC;AAhBD,sDAgBC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { createAndroidManifestPlugin } from '../plugins/android-plugins';\nimport { AndroidManifest, getMainActivityOrThrow } from './Manifest';\n\nexport const SCREEN_ORIENTATION_ATTRIBUTE = 'android:screenOrientation';\n\nexport const withOrientation = createAndroidManifestPlugin(\n setAndroidOrientation,\n 'withOrientation'\n);\n\nexport function getOrientation(config: Pick<ExpoConfig, 'orientation'>) {\n return typeof config.orientation === 'string' ? config.orientation : null;\n}\n\nexport function setAndroidOrientation(\n config: Pick<ExpoConfig, 'orientation'>,\n androidManifest: AndroidManifest\n) {\n const orientation = getOrientation(config);\n // TODO: Remove this if we decide to remove any orientation configuration when not specified\n if (!orientation) {\n return androidManifest;\n }\n\n const mainActivity = getMainActivityOrThrow(androidManifest);\n\n mainActivity.$[SCREEN_ORIENTATION_ATTRIBUTE] =\n orientation !== 'default' ? orientation : 'unspecified';\n\n return androidManifest;\n}\n"]}

View File

@ -0,0 +1,11 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
import { AndroidManifest } from './Manifest';
export declare const withPackageManifest: ConfigPlugin<void>;
export declare const withPackageGradle: ConfigPlugin;
export declare const withPackageRefactor: ConfigPlugin;
export declare function getPackage(config: Pick<ExpoConfig, 'android'>): string | null;
export declare function renamePackageOnDisk(config: Pick<ExpoConfig, 'android'>, projectRoot: string): Promise<void>;
export declare function setPackageInBuildGradle(config: Pick<ExpoConfig, 'android'>, buildGradle: string): string;
export declare function setPackageInAndroidManifest(config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidManifest): AndroidManifest;
export declare function getApplicationIdAsync(projectRoot: string): Promise<string | null>;

View File

@ -0,0 +1,148 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const glob_1 = require("glob");
const path_1 = __importDefault(require("path"));
const android_plugins_1 = require("../plugins/android-plugins");
const core_plugins_1 = require("../plugins/core-plugins");
const WarningAggregator = __importStar(require("../utils/warnings"));
const Paths_1 = require("./Paths");
exports.withPackageManifest = android_plugins_1.createAndroidManifestPlugin(setPackageInAndroidManifest, 'withPackageManifest');
exports.withPackageGradle = config => {
return android_plugins_1.withAppBuildGradle(config, config => {
if (config.modResults.language === 'groovy') {
config.modResults.contents = setPackageInBuildGradle(config, config.modResults.contents);
}
else {
WarningAggregator.addWarningAndroid('android-package', `Cannot automatically configure app build.gradle if it's not groovy`);
}
return config;
});
};
exports.withPackageRefactor = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await renamePackageOnDisk(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getPackage(config) {
var _a, _b;
return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.package) !== null && _b !== void 0 ? _b : null;
}
exports.getPackage = getPackage;
function getPackageRoot(projectRoot) {
return path_1.default.join(projectRoot, 'android', 'app', 'src', 'main', 'java');
}
async function getCurrentPackageName(projectRoot) {
const packageRoot = getPackageRoot(projectRoot);
const mainApplication = await Paths_1.getMainApplicationAsync(projectRoot);
const packagePath = path_1.default.dirname(mainApplication.path);
const packagePathParts = path_1.default.relative(packageRoot, packagePath).split(path_1.default.sep).filter(Boolean);
return packagePathParts.join('.');
}
// NOTE(brentvatne): this assumes that our MainApplication.java file is in the root of the package
// this makes sense for standard react-native projects but may not apply in customized projects, so if
// we want this to be runnable in any app we need to handle other possibilities
async function renamePackageOnDisk(config, projectRoot) {
const newPackageName = getPackage(config);
if (newPackageName === null) {
return;
}
const currentPackageName = await getCurrentPackageName(projectRoot);
if (currentPackageName === newPackageName) {
return;
}
// Set up our paths
const packageRoot = getPackageRoot(projectRoot);
const currentPackagePath = path_1.default.join(packageRoot, ...currentPackageName.split('.'));
const newPackagePath = path_1.default.join(packageRoot, ...newPackageName.split('.'));
// Create the new directory
fs_extra_1.default.mkdirpSync(newPackagePath);
// Move everything from the old directory over
glob_1.sync('**/*', { cwd: currentPackagePath }).forEach(relativePath => {
const filepath = path_1.default.join(currentPackagePath, relativePath);
if (fs_extra_1.default.lstatSync(filepath).isFile()) {
fs_extra_1.default.moveSync(filepath, path_1.default.join(newPackagePath, relativePath));
}
else {
fs_extra_1.default.mkdirpSync(filepath);
}
});
// Remove the old directory recursively from com/old/package to com/old and com,
// as long as the directories are empty
const oldPathParts = currentPackageName.split('.');
while (oldPathParts.length) {
const pathToCheck = path_1.default.join(packageRoot, ...oldPathParts);
try {
const files = fs_extra_1.default.readdirSync(pathToCheck);
if (files.length === 0) {
fs_extra_1.default.rmdirSync(pathToCheck);
}
}
finally {
oldPathParts.pop();
}
}
const filesToUpdate = [
...glob_1.sync('**/*', { cwd: newPackagePath, absolute: true }),
path_1.default.join(projectRoot, 'android', 'app', 'BUCK'),
];
// Replace all occurrences of the path in the project
filesToUpdate.forEach((filepath) => {
try {
if (fs_extra_1.default.lstatSync(filepath).isFile()) {
let contents = fs_extra_1.default.readFileSync(filepath).toString();
contents = contents.replace(new RegExp(currentPackageName, 'g'), newPackageName);
fs_extra_1.default.writeFileSync(filepath, contents);
}
}
catch (_a) { }
});
}
exports.renamePackageOnDisk = renamePackageOnDisk;
function setPackageInBuildGradle(config, buildGradle) {
const packageName = getPackage(config);
if (packageName === null) {
return buildGradle;
}
const pattern = new RegExp(`applicationId ['"].*['"]`);
return buildGradle.replace(pattern, `applicationId '${packageName}'`);
}
exports.setPackageInBuildGradle = setPackageInBuildGradle;
function setPackageInAndroidManifest(config, androidManifest) {
const packageName = getPackage(config);
if (packageName) {
androidManifest.manifest.$.package = packageName;
}
else {
delete androidManifest.manifest.$.package;
}
return androidManifest;
}
exports.setPackageInAndroidManifest = setPackageInAndroidManifest;
async function getApplicationIdAsync(projectRoot) {
var _a;
const buildGradlePath = Paths_1.getAppBuildGradle(projectRoot);
if (!(await fs_extra_1.default.pathExists(buildGradlePath))) {
return null;
}
const buildGradle = await fs_extra_1.default.readFile(buildGradlePath, 'utf8');
const matchResult = buildGradle.match(/applicationId ['"](.*)['"]/);
// TODO add fallback for legacy cases to read from AndroidManifest.xml
return (_a = matchResult === null || matchResult === void 0 ? void 0 : matchResult[1]) !== null && _a !== void 0 ? _a : null;
}
exports.getApplicationIdAsync = getApplicationIdAsync;
//# sourceMappingURL=Package.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,21 @@
import { ResourceKind } from './Resources';
export interface ProjectFile<L extends string = string> {
path: string;
language: L;
contents: string;
}
export declare type GradleProjectFile = ProjectFile<'groovy' | 'kt'>;
export declare type ApplicationProjectFile = ProjectFile<'java' | 'kt'>;
export declare function getMainApplicationAsync(projectRoot: string): Promise<ApplicationProjectFile>;
export declare function getMainActivityAsync(projectRoot: string): Promise<ApplicationProjectFile>;
export declare function getProjectBuildGradleAsync(projectRoot: string): Promise<GradleProjectFile>;
export declare function getSettingsGradleAsync(projectRoot: string): Promise<GradleProjectFile>;
export declare function getAppBuildGradleAsync(projectRoot: string): Promise<GradleProjectFile>;
export declare function getAppBuildGradle(projectRoot: string): string;
export declare function getProjectPathOrThrowAsync(projectRoot: string): Promise<string>;
export declare function getAndroidManifestAsync(projectRoot: string): Promise<string>;
export declare function getResourceFolderAsync(projectRoot: string): Promise<string>;
export declare function getResourceXMLPathAsync(projectRoot: string, { kind, name }: {
kind?: ResourceKind;
name: 'colors' | 'strings' | 'styles' | string;
}): Promise<string>;

View File

@ -0,0 +1,99 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const glob_1 = require("glob");
const path = __importStar(require("path"));
const errors_1 = require("../utils/errors");
const modules_1 = require("../utils/modules");
async function getProjectFileAsync(projectRoot, name) {
const mainActivityJavaPath = glob_1.sync(path.join(projectRoot, `android/app/src/main/java/**/${name}.@(java|kt)`))[0];
errors_1.assert(mainActivityJavaPath, `Project file "${name}" does not exist in android project for root "${projectRoot}"`);
const mainActivityPathJava = path.resolve(mainActivityJavaPath, `../${name}.java`);
const mainActivityPathKotlin = path.resolve(mainActivityJavaPath, `../${name}.kt`);
const isJava = await fs_extra_1.default.pathExists(mainActivityPathJava);
const isKotlin = !isJava && (await fs_extra_1.default.pathExists(mainActivityPathKotlin));
if (!isJava && !isKotlin) {
throw new Error(`Failed to find '${name}' file for project: ${projectRoot}.`);
}
const filePath = isJava ? mainActivityPathJava : mainActivityPathKotlin;
return {
path: path.normalize(filePath),
contents: fs_extra_1.default.readFileSync(filePath, 'utf8'),
language: isJava ? 'java' : 'kt',
};
}
async function getMainApplicationAsync(projectRoot) {
return getProjectFileAsync(projectRoot, 'MainApplication');
}
exports.getMainApplicationAsync = getMainApplicationAsync;
async function getMainActivityAsync(projectRoot) {
return getProjectFileAsync(projectRoot, 'MainActivity');
}
exports.getMainActivityAsync = getMainActivityAsync;
async function getGradleFileAsync(projectRoot, gradleName) {
const groovyPath = path.resolve(projectRoot, `${gradleName}.gradle`);
const ktPath = path.resolve(projectRoot, `${gradleName}.gradle.kts`);
const isGroovy = await fs_extra_1.default.pathExists(groovyPath);
const isKotlin = !isGroovy && (await fs_extra_1.default.pathExists(ktPath));
if (!isGroovy && !isKotlin) {
throw new Error(`Failed to find '${gradleName}.gradle' file for project: ${projectRoot}.`);
}
const filePath = isGroovy ? groovyPath : ktPath;
return {
path: path.normalize(filePath),
contents: fs_extra_1.default.readFileSync(filePath, 'utf8'),
language: isGroovy ? 'groovy' : 'kt',
};
}
async function getProjectBuildGradleAsync(projectRoot) {
return getGradleFileAsync(path.join(projectRoot, 'android'), 'build');
}
exports.getProjectBuildGradleAsync = getProjectBuildGradleAsync;
async function getSettingsGradleAsync(projectRoot) {
return getGradleFileAsync(path.join(projectRoot, 'android'), 'settings');
}
exports.getSettingsGradleAsync = getSettingsGradleAsync;
async function getAppBuildGradleAsync(projectRoot) {
return getGradleFileAsync(path.join(projectRoot, 'android', 'app'), 'build');
}
exports.getAppBuildGradleAsync = getAppBuildGradleAsync;
function getAppBuildGradle(projectRoot) {
return path.join(projectRoot, 'android', 'app', 'build.gradle');
}
exports.getAppBuildGradle = getAppBuildGradle;
async function getProjectPathOrThrowAsync(projectRoot) {
const projectPath = path.join(projectRoot, 'android');
if (await modules_1.directoryExistsAsync(projectPath)) {
return projectPath;
}
throw new Error(`Android project folder is missing in project: ${projectRoot}`);
}
exports.getProjectPathOrThrowAsync = getProjectPathOrThrowAsync;
async function getAndroidManifestAsync(projectRoot) {
const projectPath = await getProjectPathOrThrowAsync(projectRoot);
const filePath = path.join(projectPath, 'app/src/main/AndroidManifest.xml');
return filePath;
}
exports.getAndroidManifestAsync = getAndroidManifestAsync;
async function getResourceFolderAsync(projectRoot) {
const projectPath = await getProjectPathOrThrowAsync(projectRoot);
return path.join(projectPath, `app/src/main/res`);
}
exports.getResourceFolderAsync = getResourceFolderAsync;
async function getResourceXMLPathAsync(projectRoot, { kind = 'values', name }) {
const resourcePath = await getResourceFolderAsync(projectRoot);
const filePath = path.join(resourcePath, `${kind}/${name}.xml`);
return filePath;
}
exports.getResourceXMLPathAsync = getResourceXMLPathAsync;
//# sourceMappingURL=Paths.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,18 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
import { AndroidManifest, ManifestUsesPermission } from './Manifest';
export declare const requiredPermissions: string[];
export declare const allPermissions: string[];
export declare const withPermissions: ConfigPlugin<string[] | void>;
export declare function getAndroidPermissions(config: Pick<ExpoConfig, 'android'>): string[];
export declare function setAndroidPermissions(config: Pick<ExpoConfig, 'android'>, androidManifest: AndroidManifest): AndroidManifest;
export declare function isPermissionAlreadyRequested(permission: string, manifestPermissions: ManifestUsesPermission[]): boolean;
export declare function addPermissionToManifest(permission: string, manifestPermissions: ManifestUsesPermission[]): ManifestUsesPermission[];
export declare function removePermissions(androidManifest: AndroidManifest, permissionNames?: string[]): void;
export declare function addPermission(androidManifest: AndroidManifest, permissionName: string): void;
export declare function ensurePermissions(androidManifest: AndroidManifest, permissionNames: string[]): {
[permission: string]: boolean;
};
export declare function ensurePermission(androidManifest: AndroidManifest, permissionName: string): boolean;
export declare function ensurePermissionNameFormat(permissionName: string): string;
export declare function getPermissions(androidManifest: AndroidManifest): string[];

View File

@ -0,0 +1,177 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const USES_PERMISSION = 'uses-permission';
exports.requiredPermissions = [
'android.permission.INTERNET',
'android.permission.ACCESS_NETWORK_STATE',
'android.permission.SYSTEM_ALERT_WINDOW',
'android.permission.WAKE_LOCK',
'com.google.android.c2dm.permission.RECEIVE',
];
exports.allPermissions = [
...exports.requiredPermissions,
'android.permission.ACCESS_WIFI_STATE',
'android.permission.ACCESS_COARSE_LOCATION',
'android.permission.ACCESS_FINE_LOCATION',
'android.permission.CAMERA',
'android.permission.MANAGE_DOCUMENTS',
'android.permission.READ_CONTACTS',
'android.permission.WRITE_CONTACTS',
'android.permission.READ_CALENDAR',
'android.permission.WRITE_CALENDAR',
'android.permission.READ_EXTERNAL_STORAGE',
'android.permission.READ_INTERNAL_STORAGE',
'android.permission.READ_PHONE_STATE',
'android.permission.RECORD_AUDIO',
'android.permission.USE_FINGERPRINT',
'android.permission.VIBRATE',
'android.permission.WRITE_EXTERNAL_STORAGE',
'android.permission.READ_SMS',
'com.anddoes.launcher.permission.UPDATE_COUNT',
'com.android.launcher.permission.INSTALL_SHORTCUT',
'com.google.android.gms.permission.ACTIVITY_RECOGNITION',
'com.google.android.providers.gsf.permission.READ_GSERVICES',
'com.htc.launcher.permission.READ_SETTINGS',
'com.htc.launcher.permission.UPDATE_SHORTCUT',
'com.majeur.launcher.permission.UPDATE_BADGE',
'com.sec.android.provider.badge.permission.READ',
'com.sec.android.provider.badge.permission.WRITE',
'com.sonyericsson.home.permission.BROADCAST_BADGE',
];
exports.withPermissions = (config, permissions) => {
if (Array.isArray(permissions)) {
permissions = permissions.filter(Boolean);
if (!config.android)
config.android = {};
if (!config.android.permissions)
config.android.permissions = [];
config.android.permissions = [
// @ts-ignore
...new Set(config.android.permissions.concat(permissions)),
];
}
return android_plugins_1.withAndroidManifest(config, async (config) => {
config.modResults = await setAndroidPermissions(config, config.modResults);
return config;
});
};
function prefixAndroidPermissionsIfNecessary(permissions) {
return permissions.map(permission => {
if (!permission.includes('.')) {
return `android.permission.${permission}`;
}
return permission;
});
}
function getAndroidPermissions(config) {
var _a, _b;
return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.permissions) !== null && _b !== void 0 ? _b : [];
}
exports.getAndroidPermissions = getAndroidPermissions;
function setAndroidPermissions(config, androidManifest) {
var _a;
const permissions = getAndroidPermissions(config);
let permissionsToAdd = [];
if (permissions === null) {
// Use all Expo permissions
permissionsToAdd = exports.allPermissions;
}
else {
// Use minimum required, plus any specified in permissions array
const providedPermissions = prefixAndroidPermissionsIfNecessary(permissions);
permissionsToAdd = [...providedPermissions, ...exports.requiredPermissions];
}
if (!androidManifest.manifest.hasOwnProperty('uses-permission')) {
androidManifest.manifest['uses-permission'] = [];
}
// manifest.manifest['uses-permission'] = [];
const manifestPermissions = (_a = androidManifest.manifest['uses-permission']) !== null && _a !== void 0 ? _a : [];
permissionsToAdd.forEach(permission => {
if (!isPermissionAlreadyRequested(permission, manifestPermissions)) {
addPermissionToManifest(permission, manifestPermissions);
}
});
return androidManifest;
}
exports.setAndroidPermissions = setAndroidPermissions;
function isPermissionAlreadyRequested(permission, manifestPermissions) {
return manifestPermissions.some(e => e.$['android:name'] === permission);
}
exports.isPermissionAlreadyRequested = isPermissionAlreadyRequested;
function addPermissionToManifest(permission, manifestPermissions) {
manifestPermissions.push({ $: { 'android:name': permission } });
return manifestPermissions;
}
exports.addPermissionToManifest = addPermissionToManifest;
function removePermissions(androidManifest, permissionNames) {
const targetNames = permissionNames ? permissionNames.map(ensurePermissionNameFormat) : null;
const permissions = androidManifest.manifest[USES_PERMISSION] || [];
const nextPermissions = [];
for (const attribute of permissions) {
if (targetNames) {
// @ts-ignore: name isn't part of the type
const value = attribute.$['android:name'] || attribute.$.name;
if (!targetNames.includes(value)) {
nextPermissions.push(attribute);
}
}
}
androidManifest.manifest[USES_PERMISSION] = nextPermissions;
}
exports.removePermissions = removePermissions;
function addPermission(androidManifest, permissionName) {
const usesPermissions = androidManifest.manifest[USES_PERMISSION] || [];
usesPermissions.push({
$: { 'android:name': permissionName },
});
androidManifest.manifest[USES_PERMISSION] = usesPermissions;
}
exports.addPermission = addPermission;
function ensurePermissions(androidManifest, permissionNames) {
const permissions = getPermissions(androidManifest);
const results = {};
for (const permissionName of permissionNames) {
const targetName = ensurePermissionNameFormat(permissionName);
if (!permissions.includes(targetName)) {
addPermission(androidManifest, targetName);
results[permissionName] = true;
}
else {
results[permissionName] = false;
}
}
return results;
}
exports.ensurePermissions = ensurePermissions;
function ensurePermission(androidManifest, permissionName) {
const permissions = getPermissions(androidManifest);
const targetName = ensurePermissionNameFormat(permissionName);
if (!permissions.includes(targetName)) {
addPermission(androidManifest, targetName);
return true;
}
return false;
}
exports.ensurePermission = ensurePermission;
function ensurePermissionNameFormat(permissionName) {
if (permissionName.includes('.')) {
const com = permissionName.split('.');
const name = com.pop();
return [...com, name.toUpperCase()].join('.');
}
else {
// If shorthand form like `WRITE_CONTACTS` is provided, expand it to `android.permission.WRITE_CONTACTS`.
return ensurePermissionNameFormat(`android.permission.${permissionName}`);
}
}
exports.ensurePermissionNameFormat = ensurePermissionNameFormat;
function getPermissions(androidManifest) {
const usesPermissions = androidManifest.manifest[USES_PERMISSION] || [];
const permissions = usesPermissions.map(permissionObject => {
return permissionObject.$['android:name'] || permissionObject.$.name;
});
return permissions;
}
exports.getPermissions = getPermissions;
//# sourceMappingURL=Permissions.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
export declare const withPrimaryColor: ConfigPlugin;
export declare function getPrimaryColor(config: Pick<ExpoConfig, 'primaryColor'>): string;
export declare function setPrimaryColor(config: Pick<ExpoConfig, 'primaryColor'>, projectRoot: string): Promise<boolean>;

View File

@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_plugins_1 = require("../plugins/core-plugins");
const XML_1 = require("../utils/XML");
const Colors_1 = require("./Colors");
const Resources_1 = require("./Resources");
const Styles_1 = require("./Styles");
const COLOR_PRIMARY_KEY = 'colorPrimary';
const DEFAULT_PRIMARY_COLOR = '#023c69';
exports.withPrimaryColor = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setPrimaryColor(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getPrimaryColor(config) {
var _a;
return (_a = config.primaryColor) !== null && _a !== void 0 ? _a : DEFAULT_PRIMARY_COLOR;
}
exports.getPrimaryColor = getPrimaryColor;
async function setPrimaryColor(config, projectRoot) {
const hexString = getPrimaryColor(config);
const stylesPath = await Styles_1.getProjectStylesXMLPathAsync(projectRoot);
const colorsPath = await Colors_1.getProjectColorsXMLPathAsync(projectRoot);
let stylesJSON = await Resources_1.readResourcesXMLAsync({ path: stylesPath });
let colorsJSON = await Resources_1.readResourcesXMLAsync({ path: colorsPath });
const colorItemToAdd = Resources_1.buildResourceItem({ name: COLOR_PRIMARY_KEY, value: hexString });
const styleItemToAdd = Resources_1.buildResourceItem({
name: COLOR_PRIMARY_KEY,
value: `@color/${COLOR_PRIMARY_KEY}`,
});
colorsJSON = Colors_1.setColorItem(colorItemToAdd, colorsJSON);
stylesJSON = Styles_1.setStylesItem({
item: styleItemToAdd,
xml: stylesJSON,
parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },
});
try {
await Promise.all([
XML_1.writeXMLAsync({ path: colorsPath, xml: colorsJSON }),
XML_1.writeXMLAsync({ path: stylesPath, xml: stylesJSON }),
]);
}
catch (e) {
throw new Error(`Error setting Android primary color. Cannot write new styles.xml to ${stylesPath}.`);
}
return true;
}
exports.setPrimaryColor = setPrimaryColor;
//# sourceMappingURL=PrimaryColor.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"PrimaryColor.js","sourceRoot":"","sources":["../../src/android/PrimaryColor.ts"],"names":[],"mappings":";;AAGA,0DAA2D;AAC3D,sCAA6C;AAC7C,qCAAsE;AACtE,2CAAuE;AACvE,qCAAuE;AAEvE,MAAM,iBAAiB,GAAG,cAAc,CAAC;AACzC,MAAM,qBAAqB,GAAG,SAAS,CAAC;AAE3B,QAAA,gBAAgB,GAAiB,MAAM,CAAC,EAAE;IACrD,OAAO,+BAAgB,CAAC,MAAM,EAAE;QAC9B,SAAS;QACT,KAAK,EAAC,MAAM,EAAC,EAAE;YACb,MAAM,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,SAAgB,eAAe,CAAC,MAAwC;;IACtE,aAAO,MAAM,CAAC,YAAY,mCAAI,qBAAqB,CAAC;AACtD,CAAC;AAFD,0CAEC;AAEM,KAAK,UAAU,eAAe,CACnC,MAAwC,EACxC,WAAmB;IAEnB,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAE1C,MAAM,UAAU,GAAG,MAAM,qCAA4B,CAAC,WAAW,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,MAAM,qCAA4B,CAAC,WAAW,CAAC,CAAC;IAEnE,IAAI,UAAU,GAAG,MAAM,iCAAqB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACnE,IAAI,UAAU,GAAG,MAAM,iCAAqB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAEnE,MAAM,cAAc,GAAG,6BAAiB,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACxF,MAAM,cAAc,GAAG,6BAAiB,CAAC;QACvC,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,UAAU,iBAAiB,EAAE;KACrC,CAAC,CAAC;IAEH,UAAU,GAAG,qBAAY,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACtD,UAAU,GAAG,sBAAa,CAAC;QACzB,IAAI,EAAE,cAAc;QACpB,GAAG,EAAE,UAAU;QACf,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,mCAAmC,EAAE;KAC1E,CAAC,CAAC;IAEH,IAAI;QACF,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,mBAAa,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;YACpD,mBAAa,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;SACrD,CAAC,CAAC;KACJ;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,IAAI,KAAK,CACb,uEAAuE,UAAU,GAAG,CACrF,CAAC;KACH;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AApCD,0CAoCC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { ConfigPlugin } from '../Plugin.types';\nimport { withDangerousMod } from '../plugins/core-plugins';\nimport { writeXMLAsync } from '../utils/XML';\nimport { getProjectColorsXMLPathAsync, setColorItem } from './Colors';\nimport { buildResourceItem, readResourcesXMLAsync } from './Resources';\nimport { getProjectStylesXMLPathAsync, setStylesItem } from './Styles';\n\nconst COLOR_PRIMARY_KEY = 'colorPrimary';\nconst DEFAULT_PRIMARY_COLOR = '#023c69';\n\nexport const withPrimaryColor: ConfigPlugin = config => {\n return withDangerousMod(config, [\n 'android',\n async config => {\n await setPrimaryColor(config, config.modRequest.projectRoot);\n return config;\n },\n ]);\n};\n\nexport function getPrimaryColor(config: Pick<ExpoConfig, 'primaryColor'>) {\n return config.primaryColor ?? DEFAULT_PRIMARY_COLOR;\n}\n\nexport async function setPrimaryColor(\n config: Pick<ExpoConfig, 'primaryColor'>,\n projectRoot: string\n) {\n const hexString = getPrimaryColor(config);\n\n const stylesPath = await getProjectStylesXMLPathAsync(projectRoot);\n const colorsPath = await getProjectColorsXMLPathAsync(projectRoot);\n\n let stylesJSON = await readResourcesXMLAsync({ path: stylesPath });\n let colorsJSON = await readResourcesXMLAsync({ path: colorsPath });\n\n const colorItemToAdd = buildResourceItem({ name: COLOR_PRIMARY_KEY, value: hexString });\n const styleItemToAdd = buildResourceItem({\n name: COLOR_PRIMARY_KEY,\n value: `@color/${COLOR_PRIMARY_KEY}`,\n });\n\n colorsJSON = setColorItem(colorItemToAdd, colorsJSON);\n stylesJSON = setStylesItem({\n item: styleItemToAdd,\n xml: stylesJSON,\n parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },\n });\n\n try {\n await Promise.all([\n writeXMLAsync({ path: colorsPath, xml: colorsJSON }),\n writeXMLAsync({ path: stylesPath, xml: stylesJSON }),\n ]);\n } catch (e) {\n throw new Error(\n `Error setting Android primary color. Cannot write new styles.xml to ${stylesPath}.`\n );\n }\n return true;\n}\n"]}

View File

@ -0,0 +1,12 @@
export declare type PropertiesItem = {
type: 'comment';
value: string;
} | {
type: 'empty';
} | {
type: 'property';
key: string;
value: string;
};
export declare function parsePropertiesFile(contents: string): PropertiesItem[];
export declare function propertiesListToString(props: PropertiesItem[]): string;

View File

@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function parsePropertiesFile(contents) {
const propertiesList = [];
const lines = contents.split('\n');
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (!line) {
propertiesList.push({ type: 'empty' });
}
else if (line.startsWith('#')) {
propertiesList.push({ type: 'comment', value: line.substring(1).trimStart() });
}
else {
const eok = line.indexOf('=');
const key = line.slice(0, eok);
const value = line.slice(eok + 1, line.length);
propertiesList.push({ type: 'property', key, value });
}
}
return propertiesList;
}
exports.parsePropertiesFile = parsePropertiesFile;
function propertiesListToString(props) {
let output = '';
for (let i = 0; i < props.length; i++) {
const prop = props[i];
if (prop.type === 'empty') {
output += '';
}
else if (prop.type === 'comment') {
output += '# ' + prop.value;
}
else if (prop.type === 'property') {
output += `${prop.key}=${prop.value}`;
}
else {
// @ts-ignore: assertion
throw new Error(`Invalid properties type "${prop.type}"`);
}
if (i < props.length - 1) {
output += '\n';
}
}
return output;
}
exports.propertiesListToString = propertiesListToString;
//# sourceMappingURL=Properties.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Properties.js","sourceRoot":"","sources":["../../src/android/Properties.ts"],"names":[],"mappings":";;AAcA,SAAgB,mBAAmB,CAAC,QAAgB;IAClD,MAAM,cAAc,GAAqB,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,EAAE;YACT,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;SACxC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;YAC/B,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;SAChF;aAAM;YACL,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;SACvD;KACF;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAlBD,kDAkBC;AAED,SAAgB,sBAAsB,CAAC,KAAuB;IAC5D,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;YACzB,MAAM,IAAI,EAAE,CAAC;SACd;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE;YAClC,MAAM,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;SAC7B;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE;YACnC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;SACvC;aAAM;YACL,wBAAwB;YACxB,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;SAC3D;QACD,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;YACxB,MAAM,IAAI,IAAI,CAAC;SAChB;KACF;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAnBD,wDAmBC","sourcesContent":["export type PropertiesItem =\n | {\n type: 'comment';\n value: string;\n }\n | {\n type: 'empty';\n }\n | {\n type: 'property';\n key: string;\n value: string;\n };\n\nexport function parsePropertiesFile(contents: string): PropertiesItem[] {\n const propertiesList: PropertiesItem[] = [];\n const lines = contents.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n if (!line) {\n propertiesList.push({ type: 'empty' });\n } else if (line.startsWith('#')) {\n propertiesList.push({ type: 'comment', value: line.substring(1).trimStart() });\n } else {\n const eok = line.indexOf('=');\n const key = line.slice(0, eok);\n const value = line.slice(eok + 1, line.length);\n propertiesList.push({ type: 'property', key, value });\n }\n }\n\n return propertiesList;\n}\n\nexport function propertiesListToString(props: PropertiesItem[]): string {\n let output = '';\n for (let i = 0; i < props.length; i++) {\n const prop = props[i];\n if (prop.type === 'empty') {\n output += '';\n } else if (prop.type === 'comment') {\n output += '# ' + prop.value;\n } else if (prop.type === 'property') {\n output += `${prop.key}=${prop.value}`;\n } else {\n // @ts-ignore: assertion\n throw new Error(`Invalid properties type \"${prop.type}\"`);\n }\n if (i < props.length - 1) {\n output += '\\n';\n }\n }\n return output;\n}\n"]}

View File

@ -0,0 +1,57 @@
import { XMLObject } from '../utils/XML';
export declare type ResourceGroupXML = {
$: {
name: string;
parent: string;
};
item: ResourceItemXML[];
};
export declare type ResourceXML = {
resources: {
color?: ResourceItemXML[];
string?: ResourceItemXML[];
style?: ResourceGroupXML[];
};
};
export declare type ResourceItemXML = {
_: string;
$: {
name: string;
};
};
/**
* Name of the resource folder.
*/
export declare type ResourceKind = 'values' | 'values-night' | 'values-v23';
/**
* Read an XML file while providing a default fallback for resource files.
*
* @param options path to the XML file, returns a fallback XML if the path doesn't exist.
*/
export declare function readResourcesXMLAsync({ path, fallback, }: {
path: string;
fallback?: string | null;
}): Promise<ResourceXML>;
/**
* Ensure the provided xml has a `resources` object (the expected shape).
*
* @param xml
*/
export declare function ensureDefaultResourceXML(xml: XMLObject): ResourceXML;
/**
* Build a `ResourceItemXML` given its `name` and `value`. This makes things a bit more readable.
*
* - JSON: `{ $: { name }, _: value }`
* - XML: `<item name="NAME">VALUE</item>`
*
* @param props name and value strings.
*/
export declare function buildResourceItem({ name, value, }: {
name: string;
value: string;
}): ResourceItemXML;
export declare function buildResourceGroup(parent: {
name: string;
parent: string;
items?: ResourceItemXML[];
}): ResourceGroupXML;

View File

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const XML_1 = require("../utils/XML");
const fallbackResourceString = `<?xml version="1.0" encoding="utf-8"?><resources></resources>`;
/**
* Read an XML file while providing a default fallback for resource files.
*
* @param options path to the XML file, returns a fallback XML if the path doesn't exist.
*/
async function readResourcesXMLAsync({ path, fallback = fallbackResourceString, }) {
const xml = await XML_1.readXMLAsync({ path, fallback });
// Ensure the type is expected.
if (!xml.resources) {
xml.resources = {};
}
return xml;
}
exports.readResourcesXMLAsync = readResourcesXMLAsync;
/**
* Ensure the provided xml has a `resources` object (the expected shape).
*
* @param xml
*/
function ensureDefaultResourceXML(xml) {
if (!xml) {
xml = { resources: {} };
}
if (!xml.resources) {
xml.resources = {};
}
return xml;
}
exports.ensureDefaultResourceXML = ensureDefaultResourceXML;
/**
* Build a `ResourceItemXML` given its `name` and `value`. This makes things a bit more readable.
*
* - JSON: `{ $: { name }, _: value }`
* - XML: `<item name="NAME">VALUE</item>`
*
* @param props name and value strings.
*/
function buildResourceItem({ name, value, }) {
return { $: { name }, _: value };
}
exports.buildResourceItem = buildResourceItem;
function buildResourceGroup(parent) {
var _a;
return {
$: { name: parent.name, parent: parent.parent },
item: (_a = parent.items) !== null && _a !== void 0 ? _a : [],
};
}
exports.buildResourceGroup = buildResourceGroup;
//# sourceMappingURL=Resources.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Resources.js","sourceRoot":"","sources":["../../src/android/Resources.ts"],"names":[],"mappings":";;AAAA,sCAAuD;AA8BvD,MAAM,sBAAsB,GAAG,+DAA+D,CAAC;AAE/F;;;;GAIG;AACI,KAAK,UAAU,qBAAqB,CAAC,EAC1C,IAAI,EACJ,QAAQ,GAAG,sBAAsB,GAIlC;IACC,MAAM,GAAG,GAAG,MAAM,kBAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnD,+BAA+B;IAC/B,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE;QAClB,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC;KACpB;IACD,OAAO,GAAkB,CAAC;AAC5B,CAAC;AAbD,sDAaC;AAED;;;;GAIG;AACH,SAAgB,wBAAwB,CAAC,GAAc;IACrD,IAAI,CAAC,GAAG,EAAE;QACR,GAAG,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;KACzB;IACD,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE;QAClB,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC;KACpB;IAED,OAAO,GAAkB,CAAC;AAC5B,CAAC;AATD,4DASC;AAED;;;;;;;GAOG;AACH,SAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,KAAK,GAIN;IACC,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;AACnC,CAAC;AARD,8CAQC;AAED,SAAgB,kBAAkB,CAAC,MAIlC;;IACC,OAAO;QACL,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAC/C,IAAI,QAAE,MAAM,CAAC,KAAK,mCAAI,EAAE;KACzB,CAAC;AACJ,CAAC;AATD,gDASC","sourcesContent":["import { readXMLAsync, XMLObject } from '../utils/XML';\n\nexport type ResourceGroupXML = {\n $: {\n name: string;\n parent: string;\n };\n item: ResourceItemXML[];\n};\n\nexport type ResourceXML = {\n resources: {\n color?: ResourceItemXML[];\n string?: ResourceItemXML[];\n style?: ResourceGroupXML[];\n // Add more if needed...\n };\n};\n\nexport type ResourceItemXML = {\n _: string;\n $: {\n name: string;\n };\n};\n/**\n * Name of the resource folder.\n */\nexport type ResourceKind = 'values' | 'values-night' | 'values-v23';\n\nconst fallbackResourceString = `<?xml version=\"1.0\" encoding=\"utf-8\"?><resources></resources>`;\n\n/**\n * Read an XML file while providing a default fallback for resource files.\n *\n * @param options path to the XML file, returns a fallback XML if the path doesn't exist.\n */\nexport async function readResourcesXMLAsync({\n path,\n fallback = fallbackResourceString,\n}: {\n path: string;\n fallback?: string | null;\n}): Promise<ResourceXML> {\n const xml = await readXMLAsync({ path, fallback });\n // Ensure the type is expected.\n if (!xml.resources) {\n xml.resources = {};\n }\n return xml as ResourceXML;\n}\n\n/**\n * Ensure the provided xml has a `resources` object (the expected shape).\n *\n * @param xml\n */\nexport function ensureDefaultResourceXML(xml: XMLObject): ResourceXML {\n if (!xml) {\n xml = { resources: {} };\n }\n if (!xml.resources) {\n xml.resources = {};\n }\n\n return xml as ResourceXML;\n}\n\n/**\n * Build a `ResourceItemXML` given its `name` and `value`. This makes things a bit more readable.\n *\n * - JSON: `{ $: { name }, _: value }`\n * - XML: `<item name=\"NAME\">VALUE</item>`\n *\n * @param props name and value strings.\n */\nexport function buildResourceItem({\n name,\n value,\n}: {\n name: string;\n value: string;\n}): ResourceItemXML {\n return { $: { name }, _: value };\n}\n\nexport function buildResourceGroup(parent: {\n name: string;\n parent: string;\n items?: ResourceItemXML[];\n}): ResourceGroupXML {\n return {\n $: { name: parent.name, parent: parent.parent },\n item: parent.items ?? [],\n };\n}\n"]}

View File

@ -0,0 +1,5 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
export declare const withRootViewBackgroundColor: ConfigPlugin;
export declare function getRootViewBackgroundColor(config: Pick<ExpoConfig, 'android' | 'backgroundColor'>): string | null;
export declare function setRootViewBackgroundColor(config: Pick<ExpoConfig, 'android' | 'backgroundColor'>, projectRoot: string): Promise<boolean>;

View File

@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_plugins_1 = require("../plugins/core-plugins");
const XML_1 = require("../utils/XML");
const Colors_1 = require("./Colors");
const Resources_1 = require("./Resources");
const Styles_1 = require("./Styles");
const ANDROID_WINDOW_BACKGROUND = 'android:windowBackground';
const WINDOW_BACKGROUND_COLOR = 'activityBackground';
exports.withRootViewBackgroundColor = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setRootViewBackgroundColor(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getRootViewBackgroundColor(config) {
var _a;
if ((_a = config.android) === null || _a === void 0 ? void 0 : _a.backgroundColor) {
return config.android.backgroundColor;
}
if (config.backgroundColor) {
return config.backgroundColor;
}
return null;
}
exports.getRootViewBackgroundColor = getRootViewBackgroundColor;
async function setRootViewBackgroundColor(config, projectRoot) {
const hexString = getRootViewBackgroundColor(config);
if (!hexString) {
return false;
}
const stylesPath = await Styles_1.getProjectStylesXMLPathAsync(projectRoot);
const colorsPath = await Colors_1.getProjectColorsXMLPathAsync(projectRoot);
let stylesJSON = await Resources_1.readResourcesXMLAsync({ path: stylesPath });
let colorsJSON = await Resources_1.readResourcesXMLAsync({ path: colorsPath });
const colorItemToAdd = Resources_1.buildResourceItem({ name: WINDOW_BACKGROUND_COLOR, value: hexString });
const styleItemToAdd = Resources_1.buildResourceItem({
name: ANDROID_WINDOW_BACKGROUND,
value: `@color/${WINDOW_BACKGROUND_COLOR}`,
});
colorsJSON = Colors_1.setColorItem(colorItemToAdd, colorsJSON);
stylesJSON = Styles_1.setStylesItem({
item: styleItemToAdd,
xml: stylesJSON,
parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },
});
try {
await Promise.all([
XML_1.writeXMLAsync({ path: colorsPath, xml: colorsJSON }),
XML_1.writeXMLAsync({ path: stylesPath, xml: stylesJSON }),
]);
}
catch (e) {
throw new Error(`Error setting Android root view background color. Cannot write new styles.xml to ${stylesPath}.`);
}
return true;
}
exports.setRootViewBackgroundColor = setRootViewBackgroundColor;
//# sourceMappingURL=RootViewBackgroundColor.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"RootViewBackgroundColor.js","sourceRoot":"","sources":["../../src/android/RootViewBackgroundColor.ts"],"names":[],"mappings":";;AAGA,0DAA2D;AAC3D,sCAA6C;AAC7C,qCAAsE;AACtE,2CAAuE;AACvE,qCAAuE;AAEvE,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAC7D,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAExC,QAAA,2BAA2B,GAAiB,MAAM,CAAC,EAAE;IAChE,OAAO,+BAAgB,CAAC,MAAM,EAAE;QAC9B,SAAS;QACT,KAAK,EAAC,MAAM,EAAC,EAAE;YACb,MAAM,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YACxE,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,SAAgB,0BAA0B,CACxC,MAAuD;;IAEvD,UAAI,MAAM,CAAC,OAAO,0CAAE,eAAe,EAAE;QACnC,OAAO,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;KACvC;IACD,IAAI,MAAM,CAAC,eAAe,EAAE;QAC1B,OAAO,MAAM,CAAC,eAAe,CAAC;KAC/B;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAXD,gEAWC;AAEM,KAAK,UAAU,0BAA0B,CAC9C,MAAuD,EACvD,WAAmB;IAEnB,MAAM,SAAS,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,CAAC,SAAS,EAAE;QACd,OAAO,KAAK,CAAC;KACd;IAED,MAAM,UAAU,GAAG,MAAM,qCAA4B,CAAC,WAAW,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,MAAM,qCAA4B,CAAC,WAAW,CAAC,CAAC;IAEnE,IAAI,UAAU,GAAG,MAAM,iCAAqB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACnE,IAAI,UAAU,GAAG,MAAM,iCAAqB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAEnE,MAAM,cAAc,GAAG,6BAAiB,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9F,MAAM,cAAc,GAAG,6BAAiB,CAAC;QACvC,IAAI,EAAE,yBAAyB;QAC/B,KAAK,EAAE,UAAU,uBAAuB,EAAE;KAC3C,CAAC,CAAC;IAEH,UAAU,GAAG,qBAAY,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACtD,UAAU,GAAG,sBAAa,CAAC;QACzB,IAAI,EAAE,cAAc;QACpB,GAAG,EAAE,UAAU;QACf,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,mCAAmC,EAAE;KAC1E,CAAC,CAAC;IAEH,IAAI;QACF,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,mBAAa,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;YACpD,mBAAa,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;SACrD,CAAC,CAAC;KACJ;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,IAAI,KAAK,CACb,oFAAoF,UAAU,GAAG,CAClG,CAAC;KACH;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAvCD,gEAuCC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { ConfigPlugin } from '../Plugin.types';\nimport { withDangerousMod } from '../plugins/core-plugins';\nimport { writeXMLAsync } from '../utils/XML';\nimport { getProjectColorsXMLPathAsync, setColorItem } from './Colors';\nimport { buildResourceItem, readResourcesXMLAsync } from './Resources';\nimport { getProjectStylesXMLPathAsync, setStylesItem } from './Styles';\n\nconst ANDROID_WINDOW_BACKGROUND = 'android:windowBackground';\nconst WINDOW_BACKGROUND_COLOR = 'activityBackground';\n\nexport const withRootViewBackgroundColor: ConfigPlugin = config => {\n return withDangerousMod(config, [\n 'android',\n async config => {\n await setRootViewBackgroundColor(config, config.modRequest.projectRoot);\n return config;\n },\n ]);\n};\n\nexport function getRootViewBackgroundColor(\n config: Pick<ExpoConfig, 'android' | 'backgroundColor'>\n) {\n if (config.android?.backgroundColor) {\n return config.android.backgroundColor;\n }\n if (config.backgroundColor) {\n return config.backgroundColor;\n }\n\n return null;\n}\n\nexport async function setRootViewBackgroundColor(\n config: Pick<ExpoConfig, 'android' | 'backgroundColor'>,\n projectRoot: string\n) {\n const hexString = getRootViewBackgroundColor(config);\n if (!hexString) {\n return false;\n }\n\n const stylesPath = await getProjectStylesXMLPathAsync(projectRoot);\n const colorsPath = await getProjectColorsXMLPathAsync(projectRoot);\n\n let stylesJSON = await readResourcesXMLAsync({ path: stylesPath });\n let colorsJSON = await readResourcesXMLAsync({ path: colorsPath });\n\n const colorItemToAdd = buildResourceItem({ name: WINDOW_BACKGROUND_COLOR, value: hexString });\n const styleItemToAdd = buildResourceItem({\n name: ANDROID_WINDOW_BACKGROUND,\n value: `@color/${WINDOW_BACKGROUND_COLOR}`,\n });\n\n colorsJSON = setColorItem(colorItemToAdd, colorsJSON);\n stylesJSON = setStylesItem({\n item: styleItemToAdd,\n xml: stylesJSON,\n parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },\n });\n\n try {\n await Promise.all([\n writeXMLAsync({ path: colorsPath, xml: colorsJSON }),\n writeXMLAsync({ path: stylesPath, xml: stylesJSON }),\n ]);\n } catch (e) {\n throw new Error(\n `Error setting Android root view background color. Cannot write new styles.xml to ${stylesPath}.`\n );\n }\n return true;\n}\n"]}

View File

@ -0,0 +1,17 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidManifest } from './Manifest';
export declare type IntentFilterProps = {
actions: string[];
categories: string[];
schemes: string[];
};
export declare const withScheme: import("..").ConfigPlugin<void>;
export declare function getScheme(config: {
scheme?: string | string[];
}): string[];
export declare function setScheme(config: Pick<ExpoConfig, 'scheme' | 'android'>, androidManifest: AndroidManifest): AndroidManifest;
export declare function getSchemesFromManifest(androidManifest: AndroidManifest): string[];
export declare function ensureManifestHasValidIntentFilter(androidManifest: AndroidManifest): boolean;
export declare function hasScheme(scheme: string, androidManifest: AndroidManifest): boolean;
export declare function appendScheme(scheme: string, androidManifest: AndroidManifest): AndroidManifest;
export declare function removeScheme(scheme: string, androidManifest: AndroidManifest): AndroidManifest;

View File

@ -0,0 +1,191 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const WarningAggregator = __importStar(require("../utils/warnings"));
exports.withScheme = android_plugins_1.createAndroidManifestPlugin(setScheme, 'withScheme');
function getScheme(config) {
if (Array.isArray(config.scheme)) {
const validate = (value) => typeof value === 'string';
return config.scheme.filter(validate);
}
else if (typeof config.scheme === 'string') {
return [config.scheme];
}
return [];
}
exports.getScheme = getScheme;
// This plugin used to remove the unused schemes but this is unpredictable because other plugins could add schemes.
// The only way to reliably remove schemes from the project is to nuke the file and regenerate the code (`expo prebuild --clean`).
// Regardless, having extra schemes isn't a fatal issue and therefore a tolerable compromise is to just add new schemes that aren't currently present.
function setScheme(config, androidManifest) {
var _a, _b;
const schemes = [
...getScheme(config),
// @ts-ignore: TODO: android.scheme is an unreleased -- harder to add to turtle v1.
...getScheme((_a = config.android) !== null && _a !== void 0 ? _a : {}),
];
// Add the package name to the list of schemes for easier Google auth and parity with Turtle v1.
if ((_b = config.android) === null || _b === void 0 ? void 0 : _b.package) {
schemes.push(config.android.package);
}
if (schemes.length === 0) {
return androidManifest;
}
if (!ensureManifestHasValidIntentFilter(androidManifest)) {
WarningAggregator.addWarningAndroid('scheme', `Cannot add schemes because the provided manifest does not have a valid Activity with \`android:launchMode="singleTask"\`.\nThis guide can help you get setup properly https://expo.fyi/setup-android-uri-scheme`);
return androidManifest;
}
// Get the current schemes and remove them from the list of schemes to add.
const currentSchemes = getSchemesFromManifest(androidManifest);
for (const uri of currentSchemes) {
const index = schemes.indexOf(uri);
if (index > -1)
schemes.splice(index, 1);
}
// Now add all of the remaining schemes.
for (const uri of schemes) {
androidManifest = appendScheme(uri, androidManifest);
}
return androidManifest;
}
exports.setScheme = setScheme;
function isValidRedirectIntentFilter({ actions, categories, schemes }) {
return (actions.includes('android.intent.action.VIEW') &&
!categories.includes('android.intent.category.LAUNCHER'));
}
function propertiesFromIntentFilter(intentFilter) {
var _a, _b, _c, _d, _e, _f;
const actions = (_b = (_a = intentFilter === null || intentFilter === void 0 ? void 0 : intentFilter.action) === null || _a === void 0 ? void 0 : _a.map((data) => { var _a; return (_a = data === null || data === void 0 ? void 0 : data.$) === null || _a === void 0 ? void 0 : _a['android:name']; })) !== null && _b !== void 0 ? _b : [];
const categories = (_d = (_c = intentFilter === null || intentFilter === void 0 ? void 0 : intentFilter.category) === null || _c === void 0 ? void 0 : _c.map((data) => { var _a; return (_a = data === null || data === void 0 ? void 0 : data.$) === null || _a === void 0 ? void 0 : _a['android:name']; })) !== null && _d !== void 0 ? _d : [];
const schemes = (_f = (_e = intentFilter === null || intentFilter === void 0 ? void 0 : intentFilter.data) === null || _e === void 0 ? void 0 : _e.map((data) => { var _a; return (_a = data === null || data === void 0 ? void 0 : data.$) === null || _a === void 0 ? void 0 : _a['android:scheme']; })) !== null && _f !== void 0 ? _f : [];
return {
schemes,
actions,
categories,
};
}
function getSingleTaskIntentFilters(androidManifest) {
if (!Array.isArray(androidManifest.manifest.application))
return [];
let outputSchemes = [];
for (const application of androidManifest.manifest.application) {
const { activity } = application;
// @ts-ignore
const activities = Array.isArray(activity) ? activity : [activity];
const singleTaskActivities = activities.filter(activity => { var _a; return ((_a = activity === null || activity === void 0 ? void 0 : activity.$) === null || _a === void 0 ? void 0 : _a['android:launchMode']) === 'singleTask'; });
for (const activity of singleTaskActivities) {
const intentFilters = activity['intent-filter'];
outputSchemes = outputSchemes.concat(intentFilters);
}
}
return outputSchemes;
}
function getSchemesFromManifest(androidManifest) {
const outputSchemes = [];
const singleTaskIntentFilters = getSingleTaskIntentFilters(androidManifest);
for (const intentFilter of singleTaskIntentFilters) {
const properties = propertiesFromIntentFilter(intentFilter);
if (isValidRedirectIntentFilter(properties)) {
outputSchemes.push(properties);
}
}
return outputSchemes.reduce((prev, { schemes }) => [...prev, ...schemes], []);
}
exports.getSchemesFromManifest = getSchemesFromManifest;
function ensureManifestHasValidIntentFilter(androidManifest) {
var _a;
if (!Array.isArray(androidManifest.manifest.application)) {
return false;
}
for (const application of androidManifest.manifest.application) {
for (const activity of application.activity || []) {
if (((_a = activity === null || activity === void 0 ? void 0 : activity.$) === null || _a === void 0 ? void 0 : _a['android:launchMode']) === 'singleTask') {
for (const intentFilter of activity['intent-filter'] || []) {
// Parse valid intent filters...
const properties = propertiesFromIntentFilter(intentFilter);
if (isValidRedirectIntentFilter(properties)) {
return true;
}
}
if (!activity['intent-filter']) {
activity['intent-filter'] = [];
}
activity['intent-filter'].push({
action: [{ $: { 'android:name': 'android.intent.action.VIEW' } }],
category: [
{ $: { 'android:name': 'android.intent.category.DEFAULT' } },
{ $: { 'android:name': 'android.intent.category.BROWSABLE' } },
],
});
return true;
}
}
}
return false;
}
exports.ensureManifestHasValidIntentFilter = ensureManifestHasValidIntentFilter;
function hasScheme(scheme, androidManifest) {
const schemes = getSchemesFromManifest(androidManifest);
return schemes.includes(scheme);
}
exports.hasScheme = hasScheme;
function appendScheme(scheme, androidManifest) {
var _a;
if (!Array.isArray(androidManifest.manifest.application)) {
return androidManifest;
}
for (const application of androidManifest.manifest.application) {
for (const activity of application.activity || []) {
if (((_a = activity === null || activity === void 0 ? void 0 : activity.$) === null || _a === void 0 ? void 0 : _a['android:launchMode']) === 'singleTask') {
for (const intentFilter of activity['intent-filter'] || []) {
const properties = propertiesFromIntentFilter(intentFilter);
if (isValidRedirectIntentFilter(properties)) {
if (!intentFilter.data)
intentFilter.data = [];
intentFilter.data.push({
$: { 'android:scheme': scheme },
});
}
}
break;
}
}
}
return androidManifest;
}
exports.appendScheme = appendScheme;
function removeScheme(scheme, androidManifest) {
var _a, _b, _c, _d;
if (!Array.isArray(androidManifest.manifest.application)) {
return androidManifest;
}
for (const application of androidManifest.manifest.application) {
for (const activity of application.activity || []) {
if (((_a = activity === null || activity === void 0 ? void 0 : activity.$) === null || _a === void 0 ? void 0 : _a['android:launchMode']) === 'singleTask') {
for (const intentFilter of activity['intent-filter'] || []) {
// Parse valid intent filters...
const properties = propertiesFromIntentFilter(intentFilter);
if (isValidRedirectIntentFilter(properties)) {
for (const dataKey in (intentFilter === null || intentFilter === void 0 ? void 0 : intentFilter.data) || []) {
const data = (_b = intentFilter.data) === null || _b === void 0 ? void 0 : _b[dataKey];
if (((_c = data === null || data === void 0 ? void 0 : data.$) === null || _c === void 0 ? void 0 : _c['android:scheme']) === scheme) {
(_d = intentFilter.data) === null || _d === void 0 ? true : delete _d[dataKey];
}
}
}
}
break;
}
}
}
return androidManifest;
}
exports.removeScheme = removeScheme;
//# sourceMappingURL=Scheme.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,6 @@
import { ExpoConfig } from '@expo/config-types';
import { AndroidSplashScreenConfig } from '@expo/configure-splash-screen';
import { ConfigPlugin } from '../Plugin.types';
export declare const withSplashScreen: ConfigPlugin;
export declare function getSplashScreenConfig(config: ExpoConfig): AndroidSplashScreenConfig | undefined;
export declare function setSplashScreenAsync(config: ExpoConfig, projectRoot: string): Promise<void>;

View File

@ -0,0 +1,53 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const configure_splash_screen_1 = require("@expo/configure-splash-screen");
const core_plugins_1 = require("../plugins/core-plugins");
const WarningAggregator = __importStar(require("../utils/warnings"));
exports.withSplashScreen = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setSplashScreenAsync(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getSplashScreenConfig(config) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
if (!config.splash && !((_a = config.android) === null || _a === void 0 ? void 0 : _a.splash)) {
return;
}
const result = {
imageResizeMode: (_f = (_d = (_c = (_b = config.android) === null || _b === void 0 ? void 0 : _b.splash) === null || _c === void 0 ? void 0 : _c.resizeMode) !== null && _d !== void 0 ? _d : (_e = config.splash) === null || _e === void 0 ? void 0 : _e.resizeMode) !== null && _f !== void 0 ? _f : configure_splash_screen_1.SplashScreenImageResizeMode.CONTAIN,
backgroundColor: (_l = (_j = (_h = (_g = config.android) === null || _g === void 0 ? void 0 : _g.splash) === null || _h === void 0 ? void 0 : _h.backgroundColor) !== null && _j !== void 0 ? _j : (_k = config.splash) === null || _k === void 0 ? void 0 : _k.backgroundColor) !== null && _l !== void 0 ? _l : '#FFFFFF',
image: (_1 = (_y = (_v = (_s = (_p = (_o = (_m = config.android) === null || _m === void 0 ? void 0 : _m.splash) === null || _o === void 0 ? void 0 : _o.xxxhdpi) !== null && _p !== void 0 ? _p : (_r = (_q = config.android) === null || _q === void 0 ? void 0 : _q.splash) === null || _r === void 0 ? void 0 : _r.xxhdpi) !== null && _s !== void 0 ? _s : (_u = (_t = config.android) === null || _t === void 0 ? void 0 : _t.splash) === null || _u === void 0 ? void 0 : _u.xhdpi) !== null && _v !== void 0 ? _v : (_x = (_w = config.android) === null || _w === void 0 ? void 0 : _w.splash) === null || _x === void 0 ? void 0 : _x.hdpi) !== null && _y !== void 0 ? _y : (_0 = (_z = config.android) === null || _z === void 0 ? void 0 : _z.splash) === null || _0 === void 0 ? void 0 : _0.mdpi) !== null && _1 !== void 0 ? _1 : (_2 = config.splash) === null || _2 === void 0 ? void 0 : _2.image,
};
return result;
}
exports.getSplashScreenConfig = getSplashScreenConfig;
async function setSplashScreenAsync(config, projectRoot) {
const splashScreenIsSupported = config.sdkVersion === '39.0.0' || config.sdkVersion === '40.0.0' || !config.sdkVersion;
if (!splashScreenIsSupported) {
WarningAggregator.addWarningAndroid('splash', 'Unable to automatically configure splash screen. Please refer to the expo-splash-screen README for more information: https://github.com/expo/expo/tree/master/packages/expo-splash-screen');
return;
}
const splashConfig = getSplashScreenConfig(config);
if (!splashConfig) {
return;
}
try {
await configure_splash_screen_1.configureAndroidSplashScreen(projectRoot, splashConfig);
}
catch (e) {
WarningAggregator.addWarningAndroid('splash', e);
}
}
exports.setSplashScreenAsync = setSplashScreenAsync;
//# sourceMappingURL=SplashScreen.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"SplashScreen.js","sourceRoot":"","sources":["../../src/android/SplashScreen.ts"],"names":[],"mappings":";;;;;;;;;AACA,2EAIuC;AAGvC,0DAA2D;AAC3D,qEAAuD;AAE1C,QAAA,gBAAgB,GAAiB,MAAM,CAAC,EAAE;IACrD,OAAO,+BAAgB,CAAC,MAAM,EAAE;QAC9B,SAAS;QACT,KAAK,EAAC,MAAM,EAAC,EAAE;YACb,MAAM,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAClE,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,SAAgB,qBAAqB,CAAC,MAAkB;;IACtD,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,QAAC,MAAM,CAAC,OAAO,0CAAE,MAAM,CAAA,EAAE;QAC7C,OAAO;KACR;IAED,MAAM,MAAM,GAA8B;QACxC,eAAe,0BACb,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,UAAU,yCAClC,MAAM,CAAC,MAAM,0CAAE,UAAU,mCACzB,qDAA2B,CAAC,OAAO;QACrC,eAAe,0BACb,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,eAAe,yCAAI,MAAM,CAAC,MAAM,0CAAE,eAAe,mCAAI,SAAS;QACxF,KAAK,4CACH,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,OAAO,+CAC/B,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,MAAM,+CAC9B,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,KAAK,+CAC7B,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,IAAI,+CAC5B,MAAM,CAAC,OAAO,0CAAE,MAAM,0CAAE,IAAI,yCAC5B,MAAM,CAAC,MAAM,0CAAE,KAAK;KACvB,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAtBD,sDAsBC;AAEM,KAAK,UAAU,oBAAoB,CAAC,MAAkB,EAAE,WAAmB;IAChF,MAAM,uBAAuB,GAC3B,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IACzF,IAAI,CAAC,uBAAuB,EAAE;QAC5B,iBAAiB,CAAC,iBAAiB,CACjC,QAAQ,EACR,2LAA2L,CAC5L,CAAC;QAEF,OAAO;KACR;IAED,MAAM,YAAY,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO;KACR;IAED,IAAI;QACF,MAAM,sDAA4B,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;KAC/D;IAAC,OAAO,CAAC,EAAE;QACV,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;KAClD;AACH,CAAC;AAtBD,oDAsBC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\nimport {\n AndroidSplashScreenConfig,\n configureAndroidSplashScreen,\n SplashScreenImageResizeMode,\n} from '@expo/configure-splash-screen';\n\nimport { ConfigPlugin } from '../Plugin.types';\nimport { withDangerousMod } from '../plugins/core-plugins';\nimport * as WarningAggregator from '../utils/warnings';\n\nexport const withSplashScreen: ConfigPlugin = config => {\n return withDangerousMod(config, [\n 'android',\n async config => {\n await setSplashScreenAsync(config, config.modRequest.projectRoot);\n return config;\n },\n ]);\n};\n\nexport function getSplashScreenConfig(config: ExpoConfig): AndroidSplashScreenConfig | undefined {\n if (!config.splash && !config.android?.splash) {\n return;\n }\n\n const result: AndroidSplashScreenConfig = {\n imageResizeMode:\n config.android?.splash?.resizeMode ??\n config.splash?.resizeMode ??\n SplashScreenImageResizeMode.CONTAIN,\n backgroundColor:\n config.android?.splash?.backgroundColor ?? config.splash?.backgroundColor ?? '#FFFFFF', // white\n image:\n config.android?.splash?.xxxhdpi ??\n config.android?.splash?.xxhdpi ??\n config.android?.splash?.xhdpi ??\n config.android?.splash?.hdpi ??\n config.android?.splash?.mdpi ??\n config.splash?.image,\n };\n\n return result;\n}\n\nexport async function setSplashScreenAsync(config: ExpoConfig, projectRoot: string) {\n const splashScreenIsSupported =\n config.sdkVersion === '39.0.0' || config.sdkVersion === '40.0.0' || !config.sdkVersion;\n if (!splashScreenIsSupported) {\n WarningAggregator.addWarningAndroid(\n 'splash',\n 'Unable to automatically configure splash screen. Please refer to the expo-splash-screen README for more information: https://github.com/expo/expo/tree/master/packages/expo-splash-screen'\n );\n\n return;\n }\n\n const splashConfig = getSplashScreenConfig(config);\n if (!splashConfig) {\n return;\n }\n\n try {\n await configureAndroidSplashScreen(projectRoot, splashConfig);\n } catch (e) {\n WarningAggregator.addWarningAndroid('splash', e);\n }\n}\n"]}

View File

@ -0,0 +1,6 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
export declare const withStatusBar: ConfigPlugin;
export declare function getStatusBarColor(config: Pick<ExpoConfig, 'androidStatusBarColor' | 'androidStatusBar'>): string;
export declare function getStatusBarStyle(config: Pick<ExpoConfig, 'androidStatusBar'>): "light-content" | "dark-content";
export declare function setStatusBarConfig(config: Pick<ExpoConfig, 'androidStatusBarColor' | 'androidStatusBar'>, projectRoot: string): Promise<boolean>;

View File

@ -0,0 +1,91 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_plugins_1 = require("../plugins/core-plugins");
const XML_1 = require("../utils/XML");
const WarningAggregator = __importStar(require("../utils/warnings"));
const Colors_1 = require("./Colors");
const Resources_1 = require("./Resources");
const Styles_1 = require("./Styles");
const COLOR_PRIMARY_DARK_KEY = 'colorPrimaryDark';
const WINDOW_TRANSLUCENT_STATUS = 'android:windowTranslucentStatus';
const WINDOW_LIGHT_STATUS_BAR = 'android:windowLightStatusBar';
exports.withStatusBar = config => {
return core_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await setStatusBarConfig(config, config.modRequest.projectRoot);
return config;
},
]);
};
function getStatusBarColor(config) {
var _a;
if (config.androidStatusBarColor != null) {
WarningAggregator.addWarningAndroid('status-bar', '`androidStatusBarColor` is deprecated, use `androidStatusBar.backgroundColor` instead.');
}
return ((_a = config.androidStatusBar) === null || _a === void 0 ? void 0 : _a.backgroundColor) || 'translucent';
}
exports.getStatusBarColor = getStatusBarColor;
function getStatusBarStyle(config) {
var _a;
return ((_a = config.androidStatusBar) === null || _a === void 0 ? void 0 : _a.barStyle) || 'light-content';
}
exports.getStatusBarStyle = getStatusBarStyle;
async function setStatusBarConfig(config, projectRoot) {
const hexString = getStatusBarColor(config);
const statusBarStyle = getStatusBarStyle(config);
const stylesPath = await Styles_1.getProjectStylesXMLPathAsync(projectRoot);
const colorsPath = await Colors_1.getProjectColorsXMLPathAsync(projectRoot);
let stylesJSON = await Resources_1.readResourcesXMLAsync({ path: stylesPath });
let colorsJSON = await Resources_1.readResourcesXMLAsync({ path: colorsPath });
let styleItemToAdd;
if (hexString === 'translucent') {
// translucent status bar set in theme
styleItemToAdd = Resources_1.buildResourceItem({ name: WINDOW_TRANSLUCENT_STATUS, value: 'true' });
}
else {
// Need to add a color key to colors.xml to use in styles.xml
const colorItemToAdd = Resources_1.buildResourceItem({ name: COLOR_PRIMARY_DARK_KEY, value: hexString });
colorsJSON = Colors_1.setColorItem(colorItemToAdd, colorsJSON);
styleItemToAdd = Resources_1.buildResourceItem({
name: COLOR_PRIMARY_DARK_KEY,
value: `@color/${COLOR_PRIMARY_DARK_KEY}`,
});
}
// Default is light-content, don't need to do anything to set it
if (statusBarStyle === 'dark-content') {
const statusBarStyleItem = Resources_1.buildResourceItem({
name: WINDOW_LIGHT_STATUS_BAR,
value: `true`,
});
stylesJSON = Styles_1.setStylesItem({
item: statusBarStyleItem,
xml: stylesJSON,
parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },
});
}
stylesJSON = Styles_1.setStylesItem({
item: styleItemToAdd,
xml: stylesJSON,
parent: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' },
});
try {
await Promise.all([
XML_1.writeXMLAsync({ path: colorsPath, xml: colorsJSON }),
XML_1.writeXMLAsync({ path: stylesPath, xml: stylesJSON }),
]);
}
catch (e) {
throw new Error(`Error setting Android status bar config. Cannot write colors.xml to ${colorsPath}, or styles.xml to ${stylesPath}.`);
}
return true;
}
exports.setStatusBarConfig = setStatusBarConfig;
//# sourceMappingURL=StatusBar.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,6 @@
import { ResourceItemXML, ResourceKind, ResourceXML } from './Resources';
export declare function getProjectStringsXMLPathAsync(projectRoot: string, { kind }?: {
kind?: ResourceKind;
}): Promise<string>;
export declare function setStringItem(itemToAdd: ResourceItemXML[], stringFileContentsJSON: ResourceXML): ResourceXML;
export declare function removeStringItem(named: string, stringFileContentsJSON: ResourceXML): ResourceXML;

View File

@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Paths_1 = require("./Paths");
async function getProjectStringsXMLPathAsync(projectRoot, { kind } = {}) {
return Paths_1.getResourceXMLPathAsync(projectRoot, { kind, name: 'strings' });
}
exports.getProjectStringsXMLPathAsync = getProjectStringsXMLPathAsync;
function setStringItem(itemToAdd, stringFileContentsJSON) {
var _a;
if ((_a = stringFileContentsJSON === null || stringFileContentsJSON === void 0 ? void 0 : stringFileContentsJSON.resources) === null || _a === void 0 ? void 0 : _a.string) {
const stringNameExists = stringFileContentsJSON.resources.string.filter((e) => e.$.name === itemToAdd[0].$.name)[0];
if (stringNameExists) {
// replace the previous value
stringNameExists._ = itemToAdd[0]._;
}
else {
stringFileContentsJSON.resources.string = stringFileContentsJSON.resources.string.concat(itemToAdd);
}
}
else {
if (!stringFileContentsJSON.resources || typeof stringFileContentsJSON.resources === 'string') {
// file was empty and JSON is `{resources : ''}`
stringFileContentsJSON.resources = {};
}
stringFileContentsJSON.resources.string = itemToAdd;
}
return stringFileContentsJSON;
}
exports.setStringItem = setStringItem;
function removeStringItem(named, stringFileContentsJSON) {
var _a;
if ((_a = stringFileContentsJSON === null || stringFileContentsJSON === void 0 ? void 0 : stringFileContentsJSON.resources) === null || _a === void 0 ? void 0 : _a.string) {
const stringNameExists = stringFileContentsJSON.resources.string.findIndex((e) => e.$.name === named);
if (stringNameExists > -1) {
// replace the previous value
stringFileContentsJSON.resources.string.splice(stringNameExists, 1);
}
}
return stringFileContentsJSON;
}
exports.removeStringItem = removeStringItem;
//# sourceMappingURL=Strings.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Strings.js","sourceRoot":"","sources":["../../src/android/Strings.ts"],"names":[],"mappings":";;AAAA,mCAAkD;AAG3C,KAAK,UAAU,6BAA6B,CACjD,WAAmB,EACnB,EAAE,IAAI,KAA8B,EAAE;IAEtC,OAAO,+BAAuB,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AACzE,CAAC;AALD,sEAKC;AAED,SAAgB,aAAa,CAC3B,SAA4B,EAC5B,sBAAmC;;IAEnC,UAAI,sBAAsB,aAAtB,sBAAsB,uBAAtB,sBAAsB,CAAE,SAAS,0CAAE,MAAM,EAAE;QAC7C,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CACrE,CAAC,CAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACzD,CAAC,CAAC,CAAC,CAAC;QACL,IAAI,gBAAgB,EAAE;YACpB,6BAA6B;YAC7B,gBAAgB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACrC;aAAM;YACL,sBAAsB,CAAC,SAAS,CAAC,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CACtF,SAAS,CACV,CAAC;SACH;KACF;SAAM;QACL,IAAI,CAAC,sBAAsB,CAAC,SAAS,IAAI,OAAO,sBAAsB,CAAC,SAAS,KAAK,QAAQ,EAAE;YAC7F,gDAAgD;YAChD,sBAAsB,CAAC,SAAS,GAAG,EAAE,CAAC;SACvC;QACD,sBAAsB,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC;KACrD;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAxBD,sCAwBC;AAED,SAAgB,gBAAgB,CAAC,KAAa,EAAE,sBAAmC;;IACjF,UAAI,sBAAsB,aAAtB,sBAAsB,uBAAtB,sBAAsB,CAAE,SAAS,0CAAE,MAAM,EAAE;QAC7C,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CACxE,CAAC,CAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAC3C,CAAC;QACF,IAAI,gBAAgB,GAAG,CAAC,CAAC,EAAE;YACzB,6BAA6B;YAC7B,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;SACrE;KACF;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAXD,4CAWC","sourcesContent":["import { getResourceXMLPathAsync } from './Paths';\nimport { ResourceItemXML, ResourceKind, ResourceXML } from './Resources';\n\nexport async function getProjectStringsXMLPathAsync(\n projectRoot: string,\n { kind }: { kind?: ResourceKind } = {}\n): Promise<string> {\n return getResourceXMLPathAsync(projectRoot, { kind, name: 'strings' });\n}\n\nexport function setStringItem(\n itemToAdd: ResourceItemXML[],\n stringFileContentsJSON: ResourceXML\n): ResourceXML {\n if (stringFileContentsJSON?.resources?.string) {\n const stringNameExists = stringFileContentsJSON.resources.string.filter(\n (e: ResourceItemXML) => e.$.name === itemToAdd[0].$.name\n )[0];\n if (stringNameExists) {\n // replace the previous value\n stringNameExists._ = itemToAdd[0]._;\n } else {\n stringFileContentsJSON.resources.string = stringFileContentsJSON.resources.string.concat(\n itemToAdd\n );\n }\n } else {\n if (!stringFileContentsJSON.resources || typeof stringFileContentsJSON.resources === 'string') {\n // file was empty and JSON is `{resources : ''}`\n stringFileContentsJSON.resources = {};\n }\n stringFileContentsJSON.resources.string = itemToAdd;\n }\n return stringFileContentsJSON;\n}\n\nexport function removeStringItem(named: string, stringFileContentsJSON: ResourceXML): ResourceXML {\n if (stringFileContentsJSON?.resources?.string) {\n const stringNameExists = stringFileContentsJSON.resources.string.findIndex(\n (e: ResourceItemXML) => e.$.name === named\n );\n if (stringNameExists > -1) {\n // replace the previous value\n stringFileContentsJSON.resources.string.splice(stringNameExists, 1);\n }\n }\n return stringFileContentsJSON;\n}\n"]}

View File

@ -0,0 +1,32 @@
import { ResourceGroupXML, ResourceItemXML, ResourceKind, ResourceXML } from './Resources';
export declare function getProjectStylesXMLPathAsync(projectRoot: string, { kind }?: {
kind?: ResourceKind;
}): Promise<string>;
export declare function getStyleParent(xml: ResourceXML, parent: {
name: string;
parent?: string;
}): ResourceGroupXML | null;
export declare function getStylesItem({ name, xml, parent, }: {
name: string;
xml: ResourceXML;
parent: {
name: string;
parent: string;
};
}): ResourceItemXML | null;
export declare function setStylesItem({ item, xml, parent, }: {
item: ResourceItemXML;
xml: ResourceXML;
parent: {
name: string;
parent: string;
};
}): ResourceXML;
export declare function removeStylesItem({ name, xml, parent, }: {
name: string;
xml: ResourceXML;
parent: {
name: string;
parent: string;
};
}): ResourceXML;

View File

@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Paths_1 = require("./Paths");
const Resources_1 = require("./Resources");
async function getProjectStylesXMLPathAsync(projectRoot, { kind } = {}) {
return Paths_1.getResourceXMLPathAsync(projectRoot, { kind, name: 'styles' });
}
exports.getProjectStylesXMLPathAsync = getProjectStylesXMLPathAsync;
function ensureDefaultStyleResourceXML(xml) {
var _a;
xml = Resources_1.ensureDefaultResourceXML(xml);
if (!Array.isArray((_a = xml === null || xml === void 0 ? void 0 : xml.resources) === null || _a === void 0 ? void 0 : _a.style)) {
xml.resources.style = [];
}
return xml;
}
function getStyleParent(xml, parent) {
var _a, _b, _c, _d;
const app = (_d = (_c = (_b = (_a = xml === null || xml === void 0 ? void 0 : xml.resources) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.filter) === null || _c === void 0 ? void 0 : _c.call(_b, (e) => {
let matches = e.$.name === parent.name;
if (parent.parent != null && matches) {
matches = e.$.parent === parent.parent;
}
return matches;
})) === null || _d === void 0 ? void 0 : _d[0];
return app !== null && app !== void 0 ? app : null;
}
exports.getStyleParent = getStyleParent;
function getStylesItem({ name, xml, parent, }) {
xml = ensureDefaultStyleResourceXML(xml);
const appTheme = getStyleParent(xml, parent);
if (!appTheme) {
return null;
}
if (appTheme.item) {
const existingItem = appTheme.item.filter(_item => _item.$.name === name)[0];
// Don't want to 2 of the same item, so if one exists, we overwrite it
if (existingItem) {
return existingItem;
}
}
return null;
}
exports.getStylesItem = getStylesItem;
function setStylesItem({ item, xml, parent, }) {
xml = ensureDefaultStyleResourceXML(xml);
let appTheme = getStyleParent(xml, parent);
if (!appTheme) {
appTheme = Resources_1.buildResourceGroup(parent);
xml.resources.style.push(appTheme);
}
if (appTheme.item) {
const existingItem = appTheme.item.filter(_item => _item.$.name === item.$.name)[0];
// Don't want to 2 of the same item, so if one exists, we overwrite it
if (existingItem) {
existingItem._ = item._;
}
else {
appTheme.item.push(item);
}
}
else {
appTheme.item = [item];
}
return xml;
}
exports.setStylesItem = setStylesItem;
function removeStylesItem({ name, xml, parent, }) {
xml = ensureDefaultStyleResourceXML(xml);
const appTheme = getStyleParent(xml, parent);
if (appTheme === null || appTheme === void 0 ? void 0 : appTheme.item) {
const index = appTheme.item.findIndex((e) => e.$.name === name);
if (index > -1) {
appTheme.item.splice(index, 1);
}
}
return xml;
}
exports.removeStylesItem = removeStylesItem;
//# sourceMappingURL=Styles.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,31 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
import { AndroidManifest } from './Manifest';
declare type ExpoConfigUpdates = Pick<ExpoConfig, 'sdkVersion' | 'owner' | 'runtimeVersion' | 'updates' | 'slug'>;
export declare enum Config {
ENABLED = "expo.modules.updates.ENABLED",
CHECK_ON_LAUNCH = "expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH",
LAUNCH_WAIT_MS = "expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS",
SDK_VERSION = "expo.modules.updates.EXPO_SDK_VERSION",
RUNTIME_VERSION = "expo.modules.updates.EXPO_RUNTIME_VERSION",
UPDATE_URL = "expo.modules.updates.EXPO_UPDATE_URL",
RELEASE_CHANNEL = "expo.modules.updates.EXPO_RELEASE_CHANNEL"
}
export declare const withUpdates: ConfigPlugin<{
expoUsername: string | null;
}>;
export declare function getUpdateUrl(config: Pick<ExpoConfigUpdates, 'owner' | 'slug'>, username: string | null): string | null;
export declare function getRuntimeVersion(config: Pick<ExpoConfigUpdates, 'runtimeVersion'>): string | null;
export declare function getSDKVersion(config: Pick<ExpoConfigUpdates, 'sdkVersion'>): string | null;
export declare function getUpdatesEnabled(config: Pick<ExpoConfigUpdates, 'updates'>): boolean;
export declare function getUpdatesTimeout(config: Pick<ExpoConfigUpdates, 'updates'>): number;
export declare function getUpdatesCheckOnLaunch(config: Pick<ExpoConfigUpdates, 'updates'>): 'NEVER' | 'ALWAYS';
export declare function setUpdatesConfig(config: ExpoConfigUpdates, androidManifest: AndroidManifest, username: string | null): AndroidManifest;
export declare function setVersionsConfig(config: Pick<ExpoConfigUpdates, 'sdkVersion' | 'runtimeVersion'>, androidManifest: AndroidManifest): AndroidManifest;
export declare function ensureBuildGradleContainsConfigurationScript(projectRoot: string, buildGradleContents: string): string;
export declare function formatApplyLineForBuildGradle(projectRoot: string): string;
export declare function isBuildGradleConfigured(projectRoot: string, buildGradleContents: string): boolean;
export declare function isMainApplicationMetaDataSet(androidManifest: AndroidManifest): boolean;
export declare function isMainApplicationMetaDataSynced(config: ExpoConfigUpdates, androidManifest: AndroidManifest, username: string | null): boolean;
export declare function areVersionsSynced(config: Pick<ExpoConfigUpdates, 'runtimeVersion' | 'sdkVersion'>, androidManifest: AndroidManifest): boolean;
export {};

View File

@ -0,0 +1,164 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const resolve_from_1 = __importDefault(require("resolve-from"));
const android_plugins_1 = require("../plugins/android-plugins");
const Manifest_1 = require("./Manifest");
const CREATE_MANIFEST_ANDROID_PATH = 'expo-updates/scripts/create-manifest-android.gradle';
var Config;
(function (Config) {
Config["ENABLED"] = "expo.modules.updates.ENABLED";
Config["CHECK_ON_LAUNCH"] = "expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH";
Config["LAUNCH_WAIT_MS"] = "expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS";
Config["SDK_VERSION"] = "expo.modules.updates.EXPO_SDK_VERSION";
Config["RUNTIME_VERSION"] = "expo.modules.updates.EXPO_RUNTIME_VERSION";
Config["UPDATE_URL"] = "expo.modules.updates.EXPO_UPDATE_URL";
Config["RELEASE_CHANNEL"] = "expo.modules.updates.EXPO_RELEASE_CHANNEL";
})(Config = exports.Config || (exports.Config = {}));
exports.withUpdates = (config, { expoUsername }) => {
return android_plugins_1.withAndroidManifest(config, config => {
config.modResults = setUpdatesConfig(config, config.modResults, expoUsername);
return config;
});
};
function getUpdateUrl(config, username) {
const user = typeof config.owner === 'string' ? config.owner : username;
if (!user) {
return null;
}
return `https://exp.host/@${user}/${config.slug}`;
}
exports.getUpdateUrl = getUpdateUrl;
function getRuntimeVersion(config) {
return typeof config.runtimeVersion === 'string' ? config.runtimeVersion : null;
}
exports.getRuntimeVersion = getRuntimeVersion;
function getSDKVersion(config) {
return typeof config.sdkVersion === 'string' ? config.sdkVersion : null;
}
exports.getSDKVersion = getSDKVersion;
function getUpdatesEnabled(config) {
var _a;
return ((_a = config.updates) === null || _a === void 0 ? void 0 : _a.enabled) !== false;
}
exports.getUpdatesEnabled = getUpdatesEnabled;
function getUpdatesTimeout(config) {
var _a, _b;
return (_b = (_a = config.updates) === null || _a === void 0 ? void 0 : _a.fallbackToCacheTimeout) !== null && _b !== void 0 ? _b : 0;
}
exports.getUpdatesTimeout = getUpdatesTimeout;
function getUpdatesCheckOnLaunch(config) {
var _a, _b;
if (((_a = config.updates) === null || _a === void 0 ? void 0 : _a.checkAutomatically) === 'ON_ERROR_RECOVERY') {
return 'NEVER';
}
else if (((_b = config.updates) === null || _b === void 0 ? void 0 : _b.checkAutomatically) === 'ON_LOAD') {
return 'ALWAYS';
}
return 'ALWAYS';
}
exports.getUpdatesCheckOnLaunch = getUpdatesCheckOnLaunch;
function setUpdatesConfig(config, androidManifest, username) {
const mainApplication = Manifest_1.getMainApplicationOrThrow(androidManifest);
Manifest_1.addMetaDataItemToMainApplication(mainApplication, Config.ENABLED, String(getUpdatesEnabled(config)));
Manifest_1.addMetaDataItemToMainApplication(mainApplication, Config.CHECK_ON_LAUNCH, getUpdatesCheckOnLaunch(config));
Manifest_1.addMetaDataItemToMainApplication(mainApplication, Config.LAUNCH_WAIT_MS, String(getUpdatesTimeout(config)));
const updateUrl = getUpdateUrl(config, username);
if (updateUrl) {
Manifest_1.addMetaDataItemToMainApplication(mainApplication, Config.UPDATE_URL, updateUrl);
}
else {
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, Config.UPDATE_URL);
}
return setVersionsConfig(config, androidManifest);
}
exports.setUpdatesConfig = setUpdatesConfig;
function setVersionsConfig(config, androidManifest) {
const mainApplication = Manifest_1.getMainApplicationOrThrow(androidManifest);
const runtimeVersion = getRuntimeVersion(config);
const sdkVersion = getSDKVersion(config);
if (runtimeVersion) {
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, Config.SDK_VERSION);
Manifest_1.addMetaDataItemToMainApplication(mainApplication, Config.RUNTIME_VERSION, runtimeVersion);
}
else if (sdkVersion) {
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, Config.RUNTIME_VERSION);
Manifest_1.addMetaDataItemToMainApplication(mainApplication, Config.SDK_VERSION, sdkVersion);
}
else {
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, Config.RUNTIME_VERSION);
Manifest_1.removeMetaDataItemFromMainApplication(mainApplication, Config.SDK_VERSION);
}
return androidManifest;
}
exports.setVersionsConfig = setVersionsConfig;
function ensureBuildGradleContainsConfigurationScript(projectRoot, buildGradleContents) {
if (!isBuildGradleConfigured(projectRoot, buildGradleContents)) {
let cleanedUpBuildGradleContents;
const isBuildGradleMisconfigured = buildGradleContents
.split('\n')
.some(line => line.includes(CREATE_MANIFEST_ANDROID_PATH));
if (isBuildGradleMisconfigured) {
cleanedUpBuildGradleContents = buildGradleContents.replace(new RegExp(`(\n// Integration with Expo updates)?\n.*${CREATE_MANIFEST_ANDROID_PATH}.*\n`), '');
}
else {
cleanedUpBuildGradleContents = buildGradleContents;
}
const gradleScriptApply = formatApplyLineForBuildGradle(projectRoot);
return `${cleanedUpBuildGradleContents}\n// Integration with Expo updates\n${gradleScriptApply}\n`;
}
else {
return buildGradleContents;
}
}
exports.ensureBuildGradleContainsConfigurationScript = ensureBuildGradleContainsConfigurationScript;
function formatApplyLineForBuildGradle(projectRoot) {
const updatesGradleScriptPath = resolve_from_1.default.silent(projectRoot, CREATE_MANIFEST_ANDROID_PATH);
if (!updatesGradleScriptPath) {
throw new Error("Could not find the build script for Android. This could happen in case of outdated 'node_modules'. Run 'npm install' to make sure that it's up-to-date.");
}
const relativePath = path_1.default.relative(path_1.default.join(projectRoot, 'android', 'app'), updatesGradleScriptPath);
const posixPath = process.platform === 'win32' ? relativePath.replace(/\\/g, '/') : relativePath;
return `apply from: "${posixPath}"`;
}
exports.formatApplyLineForBuildGradle = formatApplyLineForBuildGradle;
function isBuildGradleConfigured(projectRoot, buildGradleContents) {
const androidBuildScript = formatApplyLineForBuildGradle(projectRoot);
return (buildGradleContents
.replace(/\r\n/g, '\n')
.split('\n')
// Check for both single and double quotes
.some(line => line === androidBuildScript || line === androidBuildScript.replace(/"/g, "'")));
}
exports.isBuildGradleConfigured = isBuildGradleConfigured;
function isMainApplicationMetaDataSet(androidManifest) {
const updateUrl = Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.UPDATE_URL);
const runtimeVersion = Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.RUNTIME_VERSION);
const sdkVersion = Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.SDK_VERSION);
return Boolean(updateUrl && (sdkVersion || runtimeVersion));
}
exports.isMainApplicationMetaDataSet = isMainApplicationMetaDataSet;
function isMainApplicationMetaDataSynced(config, androidManifest, username) {
return (getUpdateUrl(config, username) ===
Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.UPDATE_URL) &&
String(getUpdatesEnabled(config)) ===
Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.ENABLED) &&
String(getUpdatesTimeout(config)) ===
Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.LAUNCH_WAIT_MS) &&
getUpdatesCheckOnLaunch(config) ===
Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.CHECK_ON_LAUNCH) &&
areVersionsSynced(config, androidManifest));
}
exports.isMainApplicationMetaDataSynced = isMainApplicationMetaDataSynced;
function areVersionsSynced(config, androidManifest) {
const expectedRuntimeVersion = getRuntimeVersion(config);
const expectedSdkVersion = getSDKVersion(config);
const currentRuntimeVersion = Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.RUNTIME_VERSION);
const currentSdkVersion = Manifest_1.getMainApplicationMetaDataValue(androidManifest, Config.SDK_VERSION);
return (currentRuntimeVersion === expectedRuntimeVersion && currentSdkVersion === expectedSdkVersion);
}
exports.areVersionsSynced = areVersionsSynced;
//# sourceMappingURL=Updates.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
import { AndroidManifest } from './Manifest';
export declare const CONFIG_CHANGES_ATTRIBUTE = "android:configChanges";
export declare const ON_CONFIGURATION_CHANGED = "\npublic class MainActivity extends ReactActivity {\n\n // Added automatically by Expo Config\n @Override\n public void onConfigurationChanged(Configuration newConfig) {\n super.onConfigurationChanged(newConfig);\n Intent intent = new Intent(\"onConfigurationChanged\");\n intent.putExtra(\"newConfig\", newConfig);\n sendBroadcast(intent);\n }\n";
export declare const withUiModeManifest: ConfigPlugin<void>;
export declare const withUiModeMainActivity: ConfigPlugin;
export declare function getUserInterfaceStyle(config: Pick<ExpoConfig, 'android' | 'userInterfaceStyle'>): string | null;
export declare function setUiModeAndroidManifest(config: Pick<ExpoConfig, 'android' | 'userInterfaceStyle'>, androidManifest: AndroidManifest): AndroidManifest;
export declare function addOnConfigurationChangedMainActivity(config: Pick<ExpoConfig, 'android' | 'userInterfaceStyle'>, mainActivity: string): string;

View File

@ -0,0 +1,85 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const WarningAggregator = __importStar(require("../utils/warnings"));
const Manifest_1 = require("./Manifest");
exports.CONFIG_CHANGES_ATTRIBUTE = 'android:configChanges';
exports.ON_CONFIGURATION_CHANGED = `
public class MainActivity extends ReactActivity {
// Added automatically by Expo Config
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
sendBroadcast(intent);
}
`;
exports.withUiModeManifest = android_plugins_1.createAndroidManifestPlugin(setUiModeAndroidManifest, 'withUiModeManifest');
exports.withUiModeMainActivity = config => {
return android_plugins_1.withMainActivity(config, config => {
if (config.modResults.language === 'java') {
config.modResults.contents = addOnConfigurationChangedMainActivity(config, config.modResults.contents);
}
else {
WarningAggregator.addWarningAndroid('android-userInterfaceStyle', `Cannot automatically configure MainActivity if it's not java`);
}
return config;
});
};
function getUserInterfaceStyle(config) {
var _a, _b, _c;
return (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.userInterfaceStyle) !== null && _b !== void 0 ? _b : config.userInterfaceStyle) !== null && _c !== void 0 ? _c : null;
}
exports.getUserInterfaceStyle = getUserInterfaceStyle;
function setUiModeAndroidManifest(config, androidManifest) {
const userInterfaceStyle = getUserInterfaceStyle(config);
// TODO: Remove this if we decide to remove any uiMode configuration when not specified
if (!userInterfaceStyle) {
return androidManifest;
}
const mainActivity = Manifest_1.getMainActivityOrThrow(androidManifest);
mainActivity.$[exports.CONFIG_CHANGES_ATTRIBUTE] =
'keyboard|keyboardHidden|orientation|screenSize|uiMode';
return androidManifest;
}
exports.setUiModeAndroidManifest = setUiModeAndroidManifest;
function addOnConfigurationChangedMainActivity(config, mainActivity) {
var _a;
const userInterfaceStyle = getUserInterfaceStyle(config);
if (!userInterfaceStyle) {
return mainActivity;
}
// Cruzan: this is not ideal, but I'm not sure of a better way to handle writing to MainActivity.java
if ((_a = mainActivity.match(`onConfigurationChanged`)) === null || _a === void 0 ? void 0 : _a.length) {
return mainActivity;
}
const MainActivityWithImports = addJavaImports(mainActivity, [
'android.content.Intent',
'android.content.res.Configuration',
]);
const pattern = new RegExp(`public class MainActivity extends ReactActivity {`);
return MainActivityWithImports.replace(pattern, exports.ON_CONFIGURATION_CHANGED);
}
exports.addOnConfigurationChangedMainActivity = addOnConfigurationChangedMainActivity;
// TODO: we should have a generic utility for doing this
function addJavaImports(javaSource, javaImports) {
const lines = javaSource.split('\n');
const lineIndexWithPackageDeclaration = lines.findIndex(line => line.match(/^package .*;$/));
for (const javaImport of javaImports) {
if (!javaSource.includes(javaImport)) {
const importStatement = `import ${javaImport};`;
lines.splice(lineIndexWithPackageDeclaration + 1, 0, importStatement);
}
}
return lines.join('\n');
}
//# sourceMappingURL=UserInterfaceStyle.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
import { ExpoConfig } from '@expo/config-types';
import { ConfigPlugin } from '../Plugin.types';
export declare const withVersion: ConfigPlugin;
export declare function getVersionName(config: Pick<ExpoConfig, 'version'>): string | null;
export declare function setVersionName(config: Pick<ExpoConfig, 'version'>, buildGradle: string): string;
export declare function getVersionCode(config: Pick<ExpoConfig, 'android'>): number | null;
export declare function setVersionCode(config: Pick<ExpoConfig, 'android'>, buildGradle: string): string;

View File

@ -0,0 +1,52 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const android_plugins_1 = require("../plugins/android-plugins");
const WarningAggregator = __importStar(require("../utils/warnings"));
exports.withVersion = config => {
return android_plugins_1.withAppBuildGradle(config, config => {
if (config.modResults.language === 'groovy') {
config.modResults.contents = setVersionCode(config, config.modResults.contents);
config.modResults.contents = setVersionName(config, config.modResults.contents);
}
else {
WarningAggregator.addWarningAndroid('android-version', `Cannot automatically configure app build.gradle if it's not groovy`);
}
return config;
});
};
function getVersionName(config) {
var _a;
return (_a = config.version) !== null && _a !== void 0 ? _a : null;
}
exports.getVersionName = getVersionName;
function setVersionName(config, buildGradle) {
const versionName = getVersionName(config);
if (versionName === null) {
return buildGradle;
}
const pattern = new RegExp(`versionName ".*"`);
return buildGradle.replace(pattern, `versionName "${versionName}"`);
}
exports.setVersionName = setVersionName;
function getVersionCode(config) {
var _a, _b;
return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.versionCode) !== null && _b !== void 0 ? _b : null;
}
exports.getVersionCode = getVersionCode;
function setVersionCode(config, buildGradle) {
const versionCode = getVersionCode(config);
if (versionCode === null) {
return buildGradle;
}
const pattern = new RegExp(`versionCode.*`);
return buildGradle.replace(pattern, `versionCode ${versionCode}`);
}
exports.setVersionCode = setVersionCode;
//# sourceMappingURL=Version.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Version.js","sourceRoot":"","sources":["../../src/android/Version.ts"],"names":[],"mappings":";;;;;;;;;AAGA,gEAAgE;AAChE,qEAAuD;AAE1C,QAAA,WAAW,GAAiB,MAAM,CAAC,EAAE;IAChD,OAAO,oCAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;QACzC,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,KAAK,QAAQ,EAAE;YAC3C,MAAM,CAAC,UAAU,CAAC,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAChF,MAAM,CAAC,UAAU,CAAC,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;SACjF;aAAM;YACL,iBAAiB,CAAC,iBAAiB,CACjC,iBAAiB,EACjB,oEAAoE,CACrE,CAAC;SACH;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,SAAgB,cAAc,CAAC,MAAmC;;IAChE,aAAO,MAAM,CAAC,OAAO,mCAAI,IAAI,CAAC;AAChC,CAAC;AAFD,wCAEC;AAED,SAAgB,cAAc,CAAC,MAAmC,EAAE,WAAmB;IACrF,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,WAAW,KAAK,IAAI,EAAE;QACxB,OAAO,WAAW,CAAC;KACpB;IAED,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC/C,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,WAAW,GAAG,CAAC,CAAC;AACtE,CAAC;AARD,wCAQC;AAED,SAAgB,cAAc,CAAC,MAAmC;;IAChE,mBAAO,MAAM,CAAC,OAAO,0CAAE,WAAW,mCAAI,IAAI,CAAC;AAC7C,CAAC;AAFD,wCAEC;AAED,SAAgB,cAAc,CAAC,MAAmC,EAAE,WAAmB;IACrF,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,WAAW,KAAK,IAAI,EAAE;QACxB,OAAO,WAAW,CAAC;KACpB;IAED,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,eAAe,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,WAAW,EAAE,CAAC,CAAC;AACpE,CAAC;AARD,wCAQC","sourcesContent":["import { ExpoConfig } from '@expo/config-types';\n\nimport { ConfigPlugin } from '../Plugin.types';\nimport { withAppBuildGradle } from '../plugins/android-plugins';\nimport * as WarningAggregator from '../utils/warnings';\n\nexport const withVersion: ConfigPlugin = config => {\n return withAppBuildGradle(config, config => {\n if (config.modResults.language === 'groovy') {\n config.modResults.contents = setVersionCode(config, config.modResults.contents);\n config.modResults.contents = setVersionName(config, config.modResults.contents);\n } else {\n WarningAggregator.addWarningAndroid(\n 'android-version',\n `Cannot automatically configure app build.gradle if it's not groovy`\n );\n }\n return config;\n });\n};\n\nexport function getVersionName(config: Pick<ExpoConfig, 'version'>) {\n return config.version ?? null;\n}\n\nexport function setVersionName(config: Pick<ExpoConfig, 'version'>, buildGradle: string) {\n const versionName = getVersionName(config);\n if (versionName === null) {\n return buildGradle;\n }\n\n const pattern = new RegExp(`versionName \".*\"`);\n return buildGradle.replace(pattern, `versionName \"${versionName}\"`);\n}\n\nexport function getVersionCode(config: Pick<ExpoConfig, 'android'>) {\n return config.android?.versionCode ?? null;\n}\n\nexport function setVersionCode(config: Pick<ExpoConfig, 'android'>, buildGradle: string) {\n const versionCode = getVersionCode(config);\n if (versionCode === null) {\n return buildGradle;\n }\n\n const pattern = new RegExp(`versionCode.*`);\n return buildGradle.replace(pattern, `versionCode ${versionCode}`);\n}\n"]}

View File

@ -0,0 +1,29 @@
import * as AdMob from './AdMob';
import * as AllowBackup from './AllowBackup';
import * as Branch from './Branch';
import * as Colors from './Colors';
import * as EasBuild from './EasBuild';
import * as Facebook from './Facebook';
import * as GoogleMapsApiKey from './GoogleMapsApiKey';
import * as GoogleServices from './GoogleServices';
import * as Icon from './Icon';
import * as IntentFilters from './IntentFilters';
import * as Manifest from './Manifest';
import * as Name from './Name';
import * as NavigationBar from './NavigationBar';
import * as Notifications from './Notifications';
import * as Orientation from './Orientation';
import * as Package from './Package';
import * as Paths from './Paths';
import * as Permissions from './Permissions';
import * as PrimaryColor from './PrimaryColor';
import * as Properties from './Properties';
import * as RootViewBackgroundColor from './RootViewBackgroundColor';
import * as Scheme from './Scheme';
import * as SplashScreen from './SplashScreen';
import * as StatusBar from './StatusBar';
import * as Styles from './Styles';
import * as Updates from './Updates';
import * as UserInterfaceStyle from './UserInterfaceStyle';
import * as Version from './Version';
export { AllowBackup, EasBuild, Manifest, Branch, Colors, Facebook, GoogleMapsApiKey, AdMob, GoogleServices, Icon, IntentFilters, Name, NavigationBar, Notifications, Orientation, Package, Paths, Permissions, PrimaryColor, Properties, RootViewBackgroundColor, Scheme, SplashScreen, StatusBar, Styles, Updates, UserInterfaceStyle, Version, };

View File

@ -0,0 +1,66 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const AdMob = __importStar(require("./AdMob"));
exports.AdMob = AdMob;
const AllowBackup = __importStar(require("./AllowBackup"));
exports.AllowBackup = AllowBackup;
const Branch = __importStar(require("./Branch"));
exports.Branch = Branch;
const Colors = __importStar(require("./Colors"));
exports.Colors = Colors;
const EasBuild = __importStar(require("./EasBuild"));
exports.EasBuild = EasBuild;
const Facebook = __importStar(require("./Facebook"));
exports.Facebook = Facebook;
const GoogleMapsApiKey = __importStar(require("./GoogleMapsApiKey"));
exports.GoogleMapsApiKey = GoogleMapsApiKey;
const GoogleServices = __importStar(require("./GoogleServices"));
exports.GoogleServices = GoogleServices;
const Icon = __importStar(require("./Icon"));
exports.Icon = Icon;
const IntentFilters = __importStar(require("./IntentFilters"));
exports.IntentFilters = IntentFilters;
const Manifest = __importStar(require("./Manifest"));
exports.Manifest = Manifest;
const Name = __importStar(require("./Name"));
exports.Name = Name;
const NavigationBar = __importStar(require("./NavigationBar"));
exports.NavigationBar = NavigationBar;
const Notifications = __importStar(require("./Notifications"));
exports.Notifications = Notifications;
const Orientation = __importStar(require("./Orientation"));
exports.Orientation = Orientation;
const Package = __importStar(require("./Package"));
exports.Package = Package;
const Paths = __importStar(require("./Paths"));
exports.Paths = Paths;
const Permissions = __importStar(require("./Permissions"));
exports.Permissions = Permissions;
const PrimaryColor = __importStar(require("./PrimaryColor"));
exports.PrimaryColor = PrimaryColor;
const Properties = __importStar(require("./Properties"));
exports.Properties = Properties;
const RootViewBackgroundColor = __importStar(require("./RootViewBackgroundColor"));
exports.RootViewBackgroundColor = RootViewBackgroundColor;
const Scheme = __importStar(require("./Scheme"));
exports.Scheme = Scheme;
const SplashScreen = __importStar(require("./SplashScreen"));
exports.SplashScreen = SplashScreen;
const StatusBar = __importStar(require("./StatusBar"));
exports.StatusBar = StatusBar;
const Styles = __importStar(require("./Styles"));
exports.Styles = Styles;
const Updates = __importStar(require("./Updates"));
exports.Updates = Updates;
const UserInterfaceStyle = __importStar(require("./UserInterfaceStyle"));
exports.UserInterfaceStyle = UserInterfaceStyle;
const Version = __importStar(require("./Version"));
exports.Version = Version;
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/android/index.ts"],"names":[],"mappings":";;;;;;;;;AAAA,+CAAiC;AAqC/B,sBAAK;AApCP,2DAA6C;AA6B3C,kCAAW;AA5Bb,iDAAmC;AA+BjC,wBAAM;AA9BR,iDAAmC;AA+BjC,wBAAM;AA9BR,qDAAuC;AA2BrC,4BAAQ;AA1BV,qDAAuC;AA8BrC,4BAAQ;AA7BV,qEAAuD;AA8BrD,4CAAgB;AA7BlB,iEAAmD;AA+BjD,wCAAc;AA9BhB,6CAA+B;AA+B7B,oBAAI;AA9BN,+DAAiD;AA+B/C,sCAAa;AA9Bf,qDAAuC;AAsBrC,4BAAQ;AArBV,6CAA+B;AA8B7B,oBAAI;AA7BN,+DAAiD;AA8B/C,sCAAa;AA7Bf,+DAAiD;AA8B/C,sCAAa;AA7Bf,2DAA6C;AA8B3C,kCAAW;AA7Bb,mDAAqC;AA8BnC,0BAAO;AA7BT,+CAAiC;AA8B/B,sBAAK;AA7BP,2DAA6C;AA8B3C,kCAAW;AA7Bb,6DAA+C;AA8B7C,oCAAY;AA7Bd,yDAA2C;AA8BzC,gCAAU;AA7BZ,mFAAqE;AA8BnE,0DAAuB;AA7BzB,iDAAmC;AA8BjC,wBAAM;AA7BR,6DAA+C;AA8B7C,oCAAY;AA7Bd,uDAAyC;AA8BvC,8BAAS;AA7BX,iDAAmC;AA8BjC,wBAAM;AA7BR,mDAAqC;AA8BnC,0BAAO;AA7BT,yEAA2D;AA8BzD,gDAAkB;AA7BpB,mDAAqC;AA8BnC,0BAAO","sourcesContent":["import * as AdMob from './AdMob';\nimport * as AllowBackup from './AllowBackup';\nimport * as Branch from './Branch';\nimport * as Colors from './Colors';\nimport * as EasBuild from './EasBuild';\nimport * as Facebook from './Facebook';\nimport * as GoogleMapsApiKey from './GoogleMapsApiKey';\nimport * as GoogleServices from './GoogleServices';\nimport * as Icon from './Icon';\nimport * as IntentFilters from './IntentFilters';\nimport * as Manifest from './Manifest';\nimport * as Name from './Name';\nimport * as NavigationBar from './NavigationBar';\nimport * as Notifications from './Notifications';\nimport * as Orientation from './Orientation';\nimport * as Package from './Package';\nimport * as Paths from './Paths';\nimport * as Permissions from './Permissions';\nimport * as PrimaryColor from './PrimaryColor';\nimport * as Properties from './Properties';\nimport * as RootViewBackgroundColor from './RootViewBackgroundColor';\nimport * as Scheme from './Scheme';\nimport * as SplashScreen from './SplashScreen';\nimport * as StatusBar from './StatusBar';\nimport * as Styles from './Styles';\nimport * as Updates from './Updates';\nimport * as UserInterfaceStyle from './UserInterfaceStyle';\nimport * as Version from './Version';\n\nexport {\n AllowBackup,\n EasBuild,\n Manifest,\n Branch,\n Colors,\n Facebook,\n GoogleMapsApiKey,\n AdMob,\n GoogleServices,\n Icon,\n IntentFilters,\n Name,\n NavigationBar,\n Notifications,\n Orientation,\n Package,\n Paths,\n Permissions,\n PrimaryColor,\n Properties,\n RootViewBackgroundColor,\n Scheme,\n SplashScreen,\n StatusBar,\n Styles,\n Updates,\n UserInterfaceStyle,\n Version,\n};\n"]}

21
node_modules/@expo/config-plugins/build/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,21 @@
/**
* For internal use in Expo CLI
*/
import * as AndroidConfig from './android';
import * as IOSConfig from './ios';
import * as XML from './utils/XML';
import * as History from './utils/history';
import * as WarningAggregator from './utils/warnings';
export { IOSConfig, AndroidConfig };
export { WarningAggregator, History, XML };
export { withExpoIOSPlugins, withExpoAndroidPlugins, withExpoVersionedSDKPlugins, } from './plugins/expo-plugins';
/**
* These are the "config-plugins"
*/
export * from './Plugin.types';
export { withPlugins, withRunOnce, createRunOncePlugin, withDangerousMod, withExtendedMod, withInterceptedMod, } from './plugins/core-plugins';
export { withAppDelegate, withInfoPlist, withEntitlementsPlist, withExpoPlist, withXcodeProject, } from './plugins/ios-plugins';
export { withAndroidManifest, withStringsXml, withMainActivity, withProjectBuildGradle, withAppBuildGradle, withSettingsGradle, withGradleProperties, } from './plugins/android-plugins';
export { withStaticPlugin } from './plugins/static-plugins';
export { compileModsAsync } from './plugins/mod-compiler';
export { PluginError } from './utils/errors';

Some files were not shown because too many files have changed in this diff Show More