Skip to content

Commit 9a4f9e3

Browse files
Add out-of-the-box expo plugin support (#88)
Closes #87 Co-authored-by: robertjcolley <robertcolley04@gmail.com>
1 parent 7728058 commit 9a4f9e3

20 files changed

+6792
-84
lines changed

.gitignore

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ Figment/ios/Pods/
5151
Figment/ios/Podfile.lock
5252
Figment/ios/ngrokendpoint.txt
5353

54-
5554
# Node
5655
node_modules
5756
npm-debug.log
@@ -60,7 +59,7 @@ package-lock.lock
6059
.DS_Store
6160
local.properties
6261
build/
63-
react-viro*.tgz
62+
*.tgz
6463
yarn.lock
6564

6665
# Fastlane
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
4.44 KB
Binary file not shown.

app.plugin.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require("./dist/plugins/withViro");
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export declare const insertLinesHelper: (insert: string, target: string, contents: string, offset?: number, replace?: number) => string;
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.insertLinesHelper = void 0;
4+
const insertLinesHelper = (insert, target, contents, offset = 1, replace = 0) => {
5+
// Check that what you want to insert does not already exist
6+
if (!contents.includes(insert)) {
7+
const array = contents.split("\n");
8+
let newArray = [];
9+
if (target == "start") {
10+
newArray = [...array.slice(0, 1), insert, ...array.slice(1)];
11+
}
12+
else if (target == "end") {
13+
newArray = [...array, insert];
14+
}
15+
else {
16+
// Find the index of the target text you want to anchor your insert on
17+
let index = array.findIndex((str) => {
18+
return str.includes(target);
19+
});
20+
// Insert the wanted text around this anchor (i.e. offset / replace options)
21+
newArray = [
22+
...array.slice(0, index + offset),
23+
insert,
24+
...array.slice(index + offset + replace),
25+
];
26+
}
27+
return newArray.join("\n");
28+
}
29+
else {
30+
return contents;
31+
}
32+
};
33+
exports.insertLinesHelper = insertLinesHelper;

dist/plugins/withViro.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { ConfigPlugin } from "@expo/config-plugins";
2+
declare const withViro: ConfigPlugin;
3+
export default withViro;

dist/plugins/withViro.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
const withViroAndroid_1 = require("./withViroAndroid");
4+
const withViroIos_1 = require("./withViroIos");
5+
const withViro = (config) => {
6+
config = (0, withViroIos_1.withViroIos)(config);
7+
config = (0, withViroAndroid_1.withViroAndroid)(config);
8+
return config;
9+
};
10+
exports.default = withViro;

dist/plugins/withViroAndroid.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { ConfigPlugin } from "@expo/config-plugins";
2+
export declare const withViroAndroid: ConfigPlugin;

dist/plugins/withViroAndroid.js

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
"use strict";
2+
var __importDefault = (this && this.__importDefault) || function (mod) {
3+
return (mod && mod.__esModule) ? mod : { "default": mod };
4+
};
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
exports.withViroAndroid = void 0;
7+
const config_plugins_1 = require("@expo/config-plugins");
8+
const fs_1 = __importDefault(require("fs"));
9+
const path_1 = __importDefault(require("path"));
10+
const insertLinesHelper_1 = require("./util/insertLinesHelper");
11+
const withBranchAndroid = (config, props) => {
12+
// Directly edit MainApplication.java
13+
config = (0, config_plugins_1.withDangerousMod)(config, [
14+
"android",
15+
async (config) => {
16+
const mainApplicationPath = path_1.default.join(config.modRequest.platformProjectRoot, "app", "src", "main", "java", ...(config?.android?.package?.split?.(".") || []), "MainApplication.java");
17+
const root = config.modRequest.platformProjectRoot;
18+
fs_1.default.readFile(mainApplicationPath, "utf-8", (err, data) => {
19+
data = (0, insertLinesHelper_1.insertLinesHelper)("import com.viromedia.bridge.ReactViroPackage;", `package ${config?.android?.package};`, data);
20+
/**
21+
* ********************************************************************
22+
* Sample app.json with property config
23+
* Options: "AR", "GVR", "OVR_MOBILE"
24+
*
25+
* https://docs.expo.dev/guides/config-plugins/#using-a-plugin-in-your-app
26+
* ********************************************************************
27+
*
28+
* plugins: [
29+
* [
30+
* "@viro-community/react-viro",
31+
* {
32+
* "androidXrMode": "GVR"
33+
* }
34+
* ]
35+
* ],
36+
*
37+
* ********************************************************************
38+
* Sample app.json with multiple options for Viro config
39+
* ********************************************************************
40+
* plugins: [
41+
* [
42+
* "@viro-community/react-viro",
43+
* {
44+
* "androidXrMode": ["GVR", "AR"]
45+
* }
46+
* ]
47+
* ],
48+
* ********************************************************************
49+
* Sample app.json without property config
50+
* The default configuration is "AR"
51+
* ********************************************************************
52+
*
53+
* plugins: [ "@viro-community/react-viro" ],
54+
*
55+
*/
56+
const viroPlugin = config?.plugins?.find((plugin) => Array.isArray(plugin) && plugin[0] === "@viro-community/react-viro");
57+
console.log("viroPlugin", viroPlugin);
58+
let viroPluginConfig = ["AR"];
59+
if (Array.isArray(viroPlugin)) {
60+
if (Array.isArray(viroPlugin[1].androidXrMode)) {
61+
viroPluginConfig = viroPlugin[1].androidXrMode.filter((mode) => ["AR", "GVR", "OVR_MOBILE"].includes(mode));
62+
}
63+
else if (["AR", "GVR", "OVR_MOBILE"].includes(viroPlugin[1]?.androidXrMode)) {
64+
viroPluginConfig = [viroPlugin[1]?.androidXrMode];
65+
}
66+
}
67+
console.log("viroPluginConfig", viroPluginConfig);
68+
let target = "";
69+
for (const viroConfig of viroPluginConfig) {
70+
target =
71+
target +
72+
` packages.add(new ReactViroPackage(ReactViroPackage.ViroPlatform.valueOf("${viroConfig}")));\n`;
73+
}
74+
console.log("target", target);
75+
data = (0, insertLinesHelper_1.insertLinesHelper)(target, "List<ReactPackage> packages = new PackageList(this).getPackages();", data);
76+
fs_1.default.writeFile(mainApplicationPath, data, "utf-8", function (err) {
77+
if (err)
78+
console.log("Error writing MainApplication.java");
79+
});
80+
});
81+
return config;
82+
},
83+
]);
84+
return config;
85+
};
86+
const withViroProjectBuildGradle = (config) => (0, config_plugins_1.withProjectBuildGradle)(config, async (newConfig) => {
87+
newConfig.modResults.contents = newConfig.modResults.contents.replace(/minSdkVersion.*/, `minSdkVersion = 24`);
88+
newConfig.modResults.contents = newConfig.modResults.contents.replace(/classpath\("com.android.tools.build:gradle.*/, `classpath('com.android.tools.build:gradle:4.1.1')`);
89+
return newConfig;
90+
});
91+
const withViroAppBuildGradle = (config) => (0, config_plugins_1.withAppBuildGradle)(config, async (config) => {
92+
config.modResults.contents = config.modResults.contents.replace(/implementation "com.facebook.react:react-native:\+" \/\/ From node_modules/, `implementation "com.facebook.react:react-native:+" // From node_modules
93+
94+
implementation project(':gvr_common')
95+
implementation project(':arcore_client')
96+
implementation project(path: ':react_viro')
97+
implementation project(path: ':viro_renderer')
98+
implementation 'com.google.android.exoplayer:exoplayer:2.7.1'
99+
implementation 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'`);
100+
return config;
101+
});
102+
const withViroSettingsGradle = (config) => (0, config_plugins_1.withSettingsGradle)(config, async (config) => {
103+
config.modResults.contents += `
104+
include ':react_viro', ':arcore_client', ':gvr_common', ':viro_renderer'
105+
project(':arcore_client').projectDir = new File('../node_modules/@viro-community/react-viro/android/arcore_client')
106+
project(':gvr_common').projectDir = new File('../node_modules/@viro-community/react-viro/android/gvr_common')
107+
project(':viro_renderer').projectDir = new File('../node_modules/@viro-community/react-viro/android/viro_renderer')
108+
project(':react_viro').projectDir = new File('../node_modules/@viro-community/react-viro/android/react_viro')
109+
`;
110+
return config;
111+
});
112+
const withViroManifest = (config) => (0, config_plugins_1.withAndroidManifest)(config, async (newConfig) => {
113+
const contents = newConfig.modResults;
114+
contents.manifest.$["xmlns:tools"] = "http://schemas.android.com/tools";
115+
contents?.manifest?.application?.[0]["meta-data"]?.push({
116+
$: {
117+
"android:name": "com.google.ar.core",
118+
"android:value": "optional",
119+
},
120+
});
121+
contents.manifest.queries = [
122+
{
123+
package: [
124+
{
125+
$: {
126+
"android:name": "com.google.ar.core",
127+
},
128+
},
129+
],
130+
},
131+
];
132+
contents.manifest["uses-feature"] = [];
133+
contents.manifest["uses-permission"].push({
134+
$: {
135+
"android:name": "android.permission.CAMERA",
136+
},
137+
});
138+
contents.manifest["uses-feature"].push({
139+
$: {
140+
"android:name": "android.hardware.camera",
141+
},
142+
});
143+
contents.manifest["uses-feature"].push({
144+
$: {
145+
"android:name": "android.hardware.camera.autofocus",
146+
"android:required": "false",
147+
"tools:replace": "required",
148+
},
149+
});
150+
contents.manifest["uses-feature"].push({
151+
$: {
152+
"android:glEsVersion": "0x00030000",
153+
"android:required": "false",
154+
"tools:node": "remove",
155+
"tools:replace": "required",
156+
},
157+
});
158+
contents.manifest["uses-feature"].push({
159+
$: {
160+
"android:name": "android.hardware.sensor.accelerometer",
161+
"android:required": "false",
162+
"tools:replace": "required",
163+
},
164+
});
165+
contents.manifest["uses-feature"].push({
166+
$: {
167+
"android:name": "android.hardware.sensor.gyroscope",
168+
"android:required": "false",
169+
"tools:replace": "required",
170+
},
171+
});
172+
return newConfig;
173+
});
174+
const withViroAndroid = (config, props) => {
175+
(0, config_plugins_1.withPlugins)(config, [[withBranchAndroid, props]]);
176+
withViroProjectBuildGradle(config);
177+
withViroManifest(config);
178+
withViroSettingsGradle(config);
179+
withViroAppBuildGradle(config);
180+
return config;
181+
};
182+
exports.withViroAndroid = withViroAndroid;

dist/plugins/withViroIos.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { ConfigPlugin } from "@expo/config-plugins";
2+
export declare const withViroIos: ConfigPlugin;

dist/plugins/withViroIos.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"use strict";
2+
var __importDefault = (this && this.__importDefault) || function (mod) {
3+
return (mod && mod.__esModule) ? mod : { "default": mod };
4+
};
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
exports.withViroIos = void 0;
7+
const config_plugins_1 = require("@expo/config-plugins");
8+
const fs_1 = __importDefault(require("fs"));
9+
const insertLinesHelper_1 = require("./util/insertLinesHelper");
10+
const withViroPods = (config) => {
11+
config = (0, config_plugins_1.withDangerousMod)(config, [
12+
"ios",
13+
async (newConfig) => {
14+
const root = newConfig.modRequest.platformProjectRoot;
15+
fs_1.default.readFile(`${root}/Podfile`, "utf-8", (err, data) => {
16+
data = (0, insertLinesHelper_1.insertLinesHelper)(` pod 'ViroReact', :path => '../node_modules/@viro-community/react-viro/ios'\n` +
17+
` pod 'ViroKit', :path => '../node_modules/@viro-community/react-viro/ios/dist/ViroRenderer/'`, "post_install do |installer|", data, -1);
18+
fs_1.default.writeFile(`${root}/Podfile`, data, "utf-8", function (err) {
19+
if (err)
20+
console.log("Error writing Podfile");
21+
});
22+
});
23+
return newConfig;
24+
},
25+
]);
26+
return config;
27+
};
28+
const withEnabledBitcode = (config) => (0, config_plugins_1.withXcodeProject)(config, async (newConfig) => {
29+
newConfig.modResults.addBuildProperty("ENABLE_BITCODE", "NO", "Release");
30+
return newConfig;
31+
});
32+
const setExcludedArchitectures = (project) => {
33+
const configurations = project.pbxXCBuildConfigurationSection();
34+
// @ts-ignore
35+
for (const { buildSettings } of Object.values(configurations || {})) {
36+
if (typeof (buildSettings === null || buildSettings === void 0
37+
? void 0
38+
: buildSettings.PRODUCT_NAME) !== "undefined") {
39+
buildSettings['"EXCLUDED_ARCHS[sdk=iphonesimulator*]"'] = '"arm64"';
40+
}
41+
}
42+
return project;
43+
};
44+
const withExcludedSimulatorArchitectures = (config) => {
45+
return (0, config_plugins_1.withXcodeProject)(config, (newConfig) => {
46+
newConfig.modResults = setExcludedArchitectures(newConfig.modResults);
47+
return newConfig;
48+
});
49+
};
50+
const withViroIos = (config, props) => {
51+
(0, config_plugins_1.withPlugins)(config, [[withViroPods, props]]);
52+
withEnabledBitcode(config);
53+
withExcludedSimulatorArchitectures(config);
54+
return config;
55+
};
56+
exports.withViroIos = withViroIos;

0 commit comments

Comments
 (0)