@apirtc/expo-apirtc-options-plugin 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/build/logger.d.ts +9 -0
- package/build/logger.js +40 -0
- package/build/static/ReactNativeApiRTC_RPK.swift +1 -0
- package/build/static/reactNativeApiRTCExpo-Bridging-Header.h +7 -2
- package/build/withAndroidPlugin.js +69 -27
- package/build/withIosBroadcastExtension.js +7 -6
- package/build/withIosRPKFiles.js +12 -11
- package/build/withPlugin.d.ts +2 -0
- package/build/withPlugin.js +4 -0
- package/package.json +6 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Apizee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ Declare the plugin in your `app.json`:
|
|
|
36
36
|
| `enableMediaProjectionService` | Enable screen sharing on Android (MediaProjection service) | `true` |
|
|
37
37
|
| `enableVideoEffects` | Enable background blur and background image replacement on Android | `true` |
|
|
38
38
|
| `appleTeamId` | Apple Team ID used for the iOS broadcast extension | `"APPLE_TEAM_ID_NOT_SET"` |
|
|
39
|
+
| `logLevel` | Plugin log verbosity: `"silent"`, `"error"`, `"warn"`, `"info"`, `"debug"` | `"warn"` |
|
|
39
40
|
|
|
40
41
|
## What does this plugin do?
|
|
41
42
|
|
|
@@ -94,3 +95,9 @@ if (Platform.OS === 'android') {
|
|
|
94
95
|
- ML Kit Selfie Segmentation (`16.0.0-beta6`) is currently in beta — there is no GA release of this library.
|
|
95
96
|
- Background effects are applied via WebRTC's `VideoProcessor` API, so both the local preview and remote peers see the processed video.
|
|
96
97
|
- For persistence across sessions, save the selected effect ID with `AsyncStorage` and re-apply it after `createStreamFromUserMedia()`.
|
|
98
|
+
|
|
99
|
+
## Contributing
|
|
100
|
+
|
|
101
|
+
Contributions are welcome! Feel free to open an issue or submit a pull request on GitHub.
|
|
102
|
+
|
|
103
|
+
This plugin is maintained by [Apizee](https://www.apizee.com).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
|
|
2
|
+
export declare function setLogLevel(level: LogLevel): void;
|
|
3
|
+
export declare function getLogLevel(): LogLevel;
|
|
4
|
+
export declare const logger: {
|
|
5
|
+
error(...args: any[]): void;
|
|
6
|
+
warn(...args: any[]): void;
|
|
7
|
+
info(...args: any[]): void;
|
|
8
|
+
debug(...args: any[]): void;
|
|
9
|
+
};
|
package/build/logger.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
exports.setLogLevel = setLogLevel;
|
|
5
|
+
exports.getLogLevel = getLogLevel;
|
|
6
|
+
const LOG_LEVELS = {
|
|
7
|
+
silent: 0,
|
|
8
|
+
error: 1,
|
|
9
|
+
warn: 2,
|
|
10
|
+
info: 3,
|
|
11
|
+
debug: 4,
|
|
12
|
+
};
|
|
13
|
+
let currentLevel = 'warn';
|
|
14
|
+
function setLogLevel(level) {
|
|
15
|
+
currentLevel = level;
|
|
16
|
+
}
|
|
17
|
+
function getLogLevel() {
|
|
18
|
+
return currentLevel;
|
|
19
|
+
}
|
|
20
|
+
function shouldLog(level) {
|
|
21
|
+
return LOG_LEVELS[level] <= LOG_LEVELS[currentLevel];
|
|
22
|
+
}
|
|
23
|
+
exports.logger = {
|
|
24
|
+
error(...args) {
|
|
25
|
+
if (shouldLog('error'))
|
|
26
|
+
console.error('[expo-apirtc]', ...args);
|
|
27
|
+
},
|
|
28
|
+
warn(...args) {
|
|
29
|
+
if (shouldLog('warn'))
|
|
30
|
+
console.warn('[expo-apirtc]', ...args);
|
|
31
|
+
},
|
|
32
|
+
info(...args) {
|
|
33
|
+
if (shouldLog('info'))
|
|
34
|
+
console.log('[expo-apirtc]', ...args);
|
|
35
|
+
},
|
|
36
|
+
debug(...args) {
|
|
37
|
+
if (shouldLog('debug'))
|
|
38
|
+
console.log('[expo-apirtc][DEBUG]', ...args);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -2,5 +2,10 @@
|
|
|
2
2
|
// Use this file to import your target's public headers that you would like to expose to Swift.
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
// React Native <= 0.75: source-based pods, headers available via HEADER_SEARCH_PATHS
|
|
6
|
+
// React Native >= 0.76: prebuilt XCFramework, headers only accessible via module import
|
|
7
|
+
#if __has_include("React/RCTEventEmitter.h")
|
|
8
|
+
#import "React/RCTEventEmitter.h"
|
|
9
|
+
#else
|
|
10
|
+
@import React;
|
|
11
|
+
#endif
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
|
+
const logger_1 = require("./logger");
|
|
39
40
|
const REQUIRED_PERMISSIONS = [
|
|
40
41
|
"android.permission.ACCESS_NETWORK_STATE",
|
|
41
42
|
"android.permission.CAMERA",
|
|
@@ -62,7 +63,26 @@ function getAndroidPackagePath(projectRoot) {
|
|
|
62
63
|
packageName = match[1];
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
|
-
// Fallback:
|
|
66
|
+
// Fallback: read from app.config.ts or app.config.js
|
|
67
|
+
if (!packageName) {
|
|
68
|
+
const configFiles = ['app.config.ts', 'app.config.js'];
|
|
69
|
+
for (const configFile of configFiles) {
|
|
70
|
+
const configPath = path.join(projectRoot, configFile);
|
|
71
|
+
if (fs.existsSync(configPath)) {
|
|
72
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
73
|
+
// Match android.package in various forms:
|
|
74
|
+
// - package: "com.example.app"
|
|
75
|
+
// - package: 'com.example.app'
|
|
76
|
+
// - "package": "com.example.app"
|
|
77
|
+
const match = configContent.match(/["']?package["']?\s*[:=]\s*["']([\w.]+)["']/);
|
|
78
|
+
if (match) {
|
|
79
|
+
packageName = match[1];
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Fallback: read from app.json
|
|
66
86
|
if (!packageName) {
|
|
67
87
|
const appJsonPath = path.join(projectRoot, 'app.json');
|
|
68
88
|
if (fs.existsSync(appJsonPath)) {
|
|
@@ -71,7 +91,7 @@ function getAndroidPackagePath(projectRoot) {
|
|
|
71
91
|
}
|
|
72
92
|
}
|
|
73
93
|
if (!packageName) {
|
|
74
|
-
throw new Error('Package name not found in AndroidManifest.xml or app.json');
|
|
94
|
+
throw new Error('Package name not found in AndroidManifest.xml, app.config.ts, app.config.js or app.json');
|
|
75
95
|
}
|
|
76
96
|
return path.join(projectRoot, 'android/app/src/main/java', ...packageName.split('.'));
|
|
77
97
|
}
|
|
@@ -98,7 +118,7 @@ function copyAndPatchJavaFiles(projectRoot) {
|
|
|
98
118
|
let content = fs.readFileSync(src, 'utf8');
|
|
99
119
|
content = content.replace(/^package\s+[\w.]+;/m, `package ${packageName};`);
|
|
100
120
|
fs.writeFileSync(dest, content, 'utf8');
|
|
101
|
-
|
|
121
|
+
logger_1.logger.info(`Copied and patched ${file} to android sources with package: ${packageName}`);
|
|
102
122
|
}
|
|
103
123
|
});
|
|
104
124
|
}
|
|
@@ -126,10 +146,10 @@ function copyAndPatchKotlinFiles(projectRoot) {
|
|
|
126
146
|
// Kotlin package declaration has no trailing semicolon
|
|
127
147
|
content = content.replace(/^package\s+[\w.]+/m, `package ${packageName}`);
|
|
128
148
|
fs.writeFileSync(dest, content, 'utf8');
|
|
129
|
-
|
|
149
|
+
logger_1.logger.info(`Copied and patched ${file} to android sources with package: ${packageName}`);
|
|
130
150
|
}
|
|
131
151
|
else {
|
|
132
|
-
|
|
152
|
+
logger_1.logger.warn(`Kotlin source not found: ${src}`);
|
|
133
153
|
}
|
|
134
154
|
});
|
|
135
155
|
}
|
|
@@ -140,13 +160,13 @@ const withAndroidPermissions = (config) => {
|
|
|
140
160
|
manifest['uses-permission'] = [];
|
|
141
161
|
}
|
|
142
162
|
REQUIRED_PERMISSIONS.forEach((permission) => {
|
|
143
|
-
|
|
163
|
+
logger_1.logger.debug('check manifest permission:', permission);
|
|
144
164
|
if (Array.isArray(manifest['uses-permission']) &&
|
|
145
165
|
!manifest['uses-permission'].some((item) => item.$ && item.$['android:name'] === permission)) {
|
|
146
166
|
manifest['uses-permission'].push({
|
|
147
167
|
$: { 'android:name': permission }
|
|
148
168
|
});
|
|
149
|
-
|
|
169
|
+
logger_1.logger.info(`Added permission: ${permission}`);
|
|
150
170
|
}
|
|
151
171
|
});
|
|
152
172
|
return config;
|
|
@@ -156,33 +176,15 @@ const withMlKitGradleDep = (config) => {
|
|
|
156
176
|
return (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
|
|
157
177
|
if (!config.modResults.contents.includes('segmentation-selfie')) {
|
|
158
178
|
config.modResults.contents = config.modResults.contents.replace(/(\s*dependencies\s*\{)/, `$1\n ${MLKIT_SEGMENTATION_DEP}`);
|
|
159
|
-
|
|
179
|
+
logger_1.logger.info('Added ML Kit segmentation-selfie dependency to app/build.gradle');
|
|
160
180
|
}
|
|
161
181
|
return config;
|
|
162
182
|
});
|
|
163
183
|
};
|
|
164
184
|
const withAndroidPlugin = (config, props) => {
|
|
165
|
-
|
|
185
|
+
logger_1.logger.info('withAndroidPlugin called with props:', props);
|
|
166
186
|
let updatedConfig = (0, config_plugins_1.withMainApplication)(config, (config) => {
|
|
167
187
|
const mainApplication = config.modResults;
|
|
168
|
-
if (props.enableMediaProjectionService === false) {
|
|
169
|
-
console.warn('Media Projection Service is disabled, skipping modifications.');
|
|
170
|
-
return config;
|
|
171
|
-
}
|
|
172
|
-
// Add WebRTCModuleOptions import
|
|
173
|
-
if (!mainApplication.contents.includes('import com.oney.WebRTCModule.WebRTCModuleOptions')) {
|
|
174
|
-
mainApplication.contents = mainApplication.contents.replace(/(package\s+[\w.]+(?:\r?\n))/, `$1\nimport com.oney.WebRTCModule.WebRTCModuleOptions\n`);
|
|
175
|
-
}
|
|
176
|
-
// Add WebRTCModuleOptions code at start of onCreate()
|
|
177
|
-
const onCreateRegex = /override fun onCreate\(\) \{\n/;
|
|
178
|
-
const customCode = [
|
|
179
|
-
' val options: WebRTCModuleOptions = WebRTCModuleOptions.getInstance()',
|
|
180
|
-
' options.enableMediaProjectionService = true\n'
|
|
181
|
-
].join('\n');
|
|
182
|
-
if (!mainApplication.contents.includes('WebRTCModuleOptions.getInstance()')) {
|
|
183
|
-
mainApplication.contents = mainApplication.contents.replace(onCreateRegex, match => `${match}${customCode}`);
|
|
184
|
-
}
|
|
185
|
-
// Add AppLifecyclePackage import and registration
|
|
186
188
|
const packageName = (() => {
|
|
187
189
|
try {
|
|
188
190
|
return getPackageName(config.modRequest.projectRoot);
|
|
@@ -191,6 +193,26 @@ const withAndroidPlugin = (config, props) => {
|
|
|
191
193
|
return null;
|
|
192
194
|
}
|
|
193
195
|
})();
|
|
196
|
+
// Add WebRTCModuleOptions (Media Projection Service) if enabled
|
|
197
|
+
if (props.enableMediaProjectionService !== false) {
|
|
198
|
+
// Add WebRTCModuleOptions import
|
|
199
|
+
if (!mainApplication.contents.includes('import com.oney.WebRTCModule.WebRTCModuleOptions')) {
|
|
200
|
+
mainApplication.contents = mainApplication.contents.replace(/(package\s+[\w.]+(?:\r?\n))/, `$1\nimport com.oney.WebRTCModule.WebRTCModuleOptions\n`);
|
|
201
|
+
}
|
|
202
|
+
// Add WebRTCModuleOptions code at start of onCreate()
|
|
203
|
+
const onCreateRegex = /override fun onCreate\(\) \{\n/;
|
|
204
|
+
const customCode = [
|
|
205
|
+
' val options: WebRTCModuleOptions = WebRTCModuleOptions.getInstance()',
|
|
206
|
+
' options.enableMediaProjectionService = true\n'
|
|
207
|
+
].join('\n');
|
|
208
|
+
if (!mainApplication.contents.includes('WebRTCModuleOptions.getInstance()')) {
|
|
209
|
+
mainApplication.contents = mainApplication.contents.replace(onCreateRegex, match => `${match}${customCode}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
logger_1.logger.info('Media Projection Service is disabled, skipping WebRTCModuleOptions modifications.');
|
|
214
|
+
}
|
|
215
|
+
// Add AppLifecyclePackage import and registration
|
|
194
216
|
if (packageName) {
|
|
195
217
|
const importLine = `import ${packageName}.AppLifecyclePackage\n`;
|
|
196
218
|
if (!mainApplication.contents.includes(importLine.trim())) {
|
|
@@ -223,6 +245,26 @@ const withAndroidPlugin = (config, props) => {
|
|
|
223
245
|
updatedConfig = withMlKitGradleDep(updatedConfig);
|
|
224
246
|
}
|
|
225
247
|
updatedConfig = withAndroidPermissions(updatedConfig);
|
|
248
|
+
// Fix NullPointerException in ReactActivityDelegate.onUserLeaveHint
|
|
249
|
+
// This crash occurs when Media Projection permission dialog pauses the activity
|
|
250
|
+
updatedConfig = (0, config_plugins_1.withMainActivity)(updatedConfig, (config) => {
|
|
251
|
+
const mainActivity = config.modResults;
|
|
252
|
+
if (!mainActivity.contents.includes('onUserLeaveHint')) {
|
|
253
|
+
// Add the override before the closing brace of the class
|
|
254
|
+
const onUserLeaveHintCode = `
|
|
255
|
+
override fun onUserLeaveHint() {
|
|
256
|
+
try {
|
|
257
|
+
super.onUserLeaveHint()
|
|
258
|
+
} catch (e: NullPointerException) {
|
|
259
|
+
// Workaround for NPE in ReactActivityDelegate.onUserLeaveHint
|
|
260
|
+
// when Media Projection permission dialog pauses the activity
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
`;
|
|
264
|
+
mainActivity.contents = mainActivity.contents.replace(/\n}\s*$/, `${onUserLeaveHintCode}\n}`);
|
|
265
|
+
}
|
|
266
|
+
return config;
|
|
267
|
+
});
|
|
226
268
|
return updatedConfig;
|
|
227
269
|
};
|
|
228
270
|
exports.default = withAndroidPlugin;
|
|
@@ -41,16 +41,17 @@ const plist_1 = __importDefault(require("@expo/plist"));
|
|
|
41
41
|
const fs = __importStar(require("fs"));
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
43
|
const util = __importStar(require("util"));
|
|
44
|
+
const logger_1 = require("./logger");
|
|
44
45
|
const quoted = (str) => {
|
|
45
46
|
return util.format(`"%s"`, str);
|
|
46
47
|
};
|
|
47
48
|
const withIosBroadcastExtension = (config, props) => {
|
|
48
|
-
|
|
49
|
+
logger_1.logger.info('withIosBroadcastExtension called with props:', props);
|
|
49
50
|
config = withAppEntitlements(config);
|
|
50
51
|
config = withInfoPlistRTC(config);
|
|
51
52
|
config = withBroadcastExtensionXcodeTarget(config, props);
|
|
52
53
|
config = withBroadcastExtensionPlist(config);
|
|
53
|
-
//TODO
|
|
54
|
+
//TODO Review this section
|
|
54
55
|
return config;
|
|
55
56
|
};
|
|
56
57
|
const withAppEntitlements = (config) => {
|
|
@@ -126,7 +127,7 @@ const withBroadcastExtensionXcodeTarget = (config, props) => {
|
|
|
126
127
|
const addBroadcastExtensionXcodeTarget = (proj, { appName, extensionName, extensionBundleIdentifier, currentProjectVersion, marketingVersion, appleTeamId, }) => {
|
|
127
128
|
var _a;
|
|
128
129
|
if (((_a = proj.getFirstProject().firstProject.targets) === null || _a === void 0 ? void 0 : _a.length) > 1) {
|
|
129
|
-
|
|
130
|
+
logger_1.logger.error("addBroadcastExtensionXcodeTarget targets?.length > 1");
|
|
130
131
|
return;
|
|
131
132
|
}
|
|
132
133
|
const targetUuid = proj.generateUuid();
|
|
@@ -172,7 +173,7 @@ const addXCConfigurationList = (proj, { extensionBundleIdentifier, currentProjec
|
|
|
172
173
|
CLANG_WARN_DOCUMENTATION_COMMENTS: 'YES',
|
|
173
174
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER: 'YES',
|
|
174
175
|
CLANG_WARN_UNGUARDED_AVAILABILITY: 'YES_AGGRESSIVE',
|
|
175
|
-
DEVELOPMENT_TEAM: appleTeamId ? quoted(appleTeamId) : undefined,
|
|
176
|
+
DEVELOPMENT_TEAM: appleTeamId ? quoted(appleTeamId) : undefined,
|
|
176
177
|
CODE_SIGN_ENTITLEMENTS: `${appName}/${appName}.entitlements`,
|
|
177
178
|
CODE_SIGN_STYLE: 'Automatic',
|
|
178
179
|
CURRENT_PROJECT_VERSION: currentProjectVersion,
|
|
@@ -350,11 +351,11 @@ const addSourceFiles = (proj, extensionRootPath) => {
|
|
|
350
351
|
const targetUuid = proj.findTargetKey('screenSharing_Extension');
|
|
351
352
|
const groupUuid = proj.findPBXGroupKey({ name: 'screenSharing_Extension' });
|
|
352
353
|
if (!targetUuid) {
|
|
353
|
-
|
|
354
|
+
logger_1.logger.error(`Failed to find "screenSharing_Extension" target!`);
|
|
354
355
|
return;
|
|
355
356
|
}
|
|
356
357
|
if (!groupUuid) {
|
|
357
|
-
|
|
358
|
+
logger_1.logger.error(`Failed to find "screenSharing_Extension" group!`);
|
|
358
359
|
return;
|
|
359
360
|
}
|
|
360
361
|
proj.addSourceFile('Atomic.swift', {
|
package/build/withIosRPKFiles.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
37
37
|
const path = __importStar(require("path"));
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
|
+
const logger_1 = require("./logger");
|
|
39
40
|
const NATIVE_FILES = [
|
|
40
41
|
'ReactNativeApiRTC_RPK.swift',
|
|
41
42
|
'ReactNativeApiRTC_RPK.m',
|
|
@@ -53,11 +54,11 @@ function copyNativeFiles(projectRoot, iosProjectName) {
|
|
|
53
54
|
const src = path.join(nativeSrcPath, file);
|
|
54
55
|
const dest = path.join(iosPath, file);
|
|
55
56
|
if (!fs.existsSync(src)) {
|
|
56
|
-
|
|
57
|
+
logger_1.logger.warn(`File not found: ${src}`);
|
|
57
58
|
continue;
|
|
58
59
|
}
|
|
59
60
|
fs.copyFileSync(src, dest);
|
|
60
|
-
|
|
61
|
+
logger_1.logger.info(`Copied: ${file}`);
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
function copyBridgingFiles(projectRoot, iosProjectName) {
|
|
@@ -67,11 +68,11 @@ function copyBridgingFiles(projectRoot, iosProjectName) {
|
|
|
67
68
|
const src = path.join(nativeSrcPath, file);
|
|
68
69
|
const dest = path.join(iosPath, file);
|
|
69
70
|
if (!fs.existsSync(src)) {
|
|
70
|
-
|
|
71
|
+
logger_1.logger.warn(`File not found: ${src}`);
|
|
71
72
|
continue;
|
|
72
73
|
}
|
|
73
74
|
fs.copyFileSync(src, dest);
|
|
74
|
-
|
|
75
|
+
logger_1.logger.info(`Copied: ${file}`);
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
const withNativeFilesPlugin = (config) => {
|
|
@@ -83,30 +84,30 @@ const withNativeFilesPlugin = (config) => {
|
|
|
83
84
|
const nativeGroup = project.getFirstProject().firstProject.mainGroup;
|
|
84
85
|
copyNativeFiles(projectRoot, iosProjectName);
|
|
85
86
|
copyBridgingFiles(projectRoot, iosProjectName);
|
|
86
|
-
//
|
|
87
|
+
// Find the Sources section (PBXSourcesBuildPhase)
|
|
87
88
|
const buildPhases = project.hash.project.objects['PBXSourcesBuildPhase'];
|
|
88
89
|
const buildPhaseEntry = Object.entries(buildPhases).find(([key, val]) => key !== 'isa' && (val === null || val === void 0 ? void 0 : val.isa) === 'PBXSourcesBuildPhase');
|
|
89
90
|
if (!buildPhaseEntry) {
|
|
90
|
-
throw new Error('
|
|
91
|
+
throw new Error('PBXSourcesBuildPhase not found in Xcode project.');
|
|
91
92
|
}
|
|
92
93
|
const [sourcesBuildPhaseUuid, sourcesBuildPhase] = buildPhaseEntry;
|
|
93
94
|
sourcesBuildPhase.files = sourcesBuildPhase.files || [];
|
|
94
95
|
for (const fileName of NATIVE_FILES) {
|
|
95
96
|
const filePath = path.join(iosDir, iosProjectName, fileName);
|
|
96
97
|
if (!fs.existsSync(filePath)) {
|
|
97
|
-
|
|
98
|
+
logger_1.logger.warn(`Native file not found: ${filePath}`);
|
|
98
99
|
continue;
|
|
99
100
|
}
|
|
100
101
|
const file = project.addFile(path.join(iosProjectName, fileName), nativeGroup);
|
|
101
102
|
if (!(file === null || file === void 0 ? void 0 : file.fileRef)) {
|
|
102
|
-
|
|
103
|
+
logger_1.logger.warn(`Failed to add: ${fileName}`);
|
|
103
104
|
continue;
|
|
104
105
|
}
|
|
105
|
-
//
|
|
106
|
+
// Check if already present
|
|
106
107
|
const alreadyExists = sourcesBuildPhase.files.some((f) => (f === null || f === void 0 ? void 0 : f.comment) === `${fileName} in Sources`);
|
|
107
108
|
if (alreadyExists)
|
|
108
109
|
continue;
|
|
109
|
-
//
|
|
110
|
+
// Create a buildFile
|
|
110
111
|
const buildFileUuid = project.generateUuid();
|
|
111
112
|
project.hash.project.objects['PBXBuildFile'][buildFileUuid] = {
|
|
112
113
|
isa: 'PBXBuildFile',
|
|
@@ -117,7 +118,7 @@ const withNativeFilesPlugin = (config) => {
|
|
|
117
118
|
value: buildFileUuid,
|
|
118
119
|
comment: `${fileName} in Sources`,
|
|
119
120
|
});
|
|
120
|
-
|
|
121
|
+
logger_1.logger.info(`File added: ${fileName}`);
|
|
121
122
|
}
|
|
122
123
|
// Swift config
|
|
123
124
|
const targetUuid = project.getFirstTarget().uuid;
|
package/build/withPlugin.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
import { LogLevel } from './logger';
|
|
2
3
|
type PluginProps = {
|
|
3
4
|
enableMediaProjectionService?: boolean;
|
|
4
5
|
enableVideoEffects?: boolean;
|
|
5
6
|
appleTeamId?: string;
|
|
7
|
+
logLevel?: LogLevel;
|
|
6
8
|
};
|
|
7
9
|
export declare const withPlugin: ConfigPlugin<PluginProps>;
|
|
8
10
|
export default withPlugin;
|
package/build/withPlugin.js
CHANGED
|
@@ -7,11 +7,15 @@ exports.withPlugin = void 0;
|
|
|
7
7
|
const withAndroidPlugin_1 = __importDefault(require("./withAndroidPlugin"));
|
|
8
8
|
const withIosBroadcastExtension_1 = __importDefault(require("./withIosBroadcastExtension"));
|
|
9
9
|
const withIosRPKFiles_1 = __importDefault(require("./withIosRPKFiles"));
|
|
10
|
+
const logger_1 = require("./logger");
|
|
10
11
|
const withPlugin = (config, props = {
|
|
11
12
|
enableMediaProjectionService: true,
|
|
12
13
|
enableVideoEffects: true,
|
|
13
14
|
appleTeamId: process.env.EXPO_APPLE_TEAM_ID || 'APPLE_TEAM_ID_NOT_SET',
|
|
14
15
|
}) => {
|
|
16
|
+
if (props.logLevel) {
|
|
17
|
+
(0, logger_1.setLogLevel)(props.logLevel);
|
|
18
|
+
}
|
|
15
19
|
config = (0, withAndroidPlugin_1.default)(config, props);
|
|
16
20
|
config = (0, withIosBroadcastExtension_1.default)(config, props);
|
|
17
21
|
config = (0, withIosRPKFiles_1.default)(config, props);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apirtc/expo-apirtc-options-plugin",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Plugin Expo pour ajouter les features apiRTC dans une application React Native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
],
|
|
13
13
|
"author": "F.Luart",
|
|
14
14
|
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/ApiRTC/expo-apirtc-options-plugin.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/ApiRTC/expo-apirtc-options-plugin#readme",
|
|
15
20
|
"dependencies": {
|
|
16
21
|
"@expo/config-plugins": "^10.1.2",
|
|
17
22
|
"@types/node": "^24.0.12",
|