@fishjam-cloud/react-native-client 0.2.1 → 0.2.2

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.
Files changed (24) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/AndroidManifest.xml +2 -0
  3. package/android/src/main/java/io/fishjam/reactnative/AudioDeviceKind.kt +34 -0
  4. package/android/src/main/java/io/fishjam/reactnative/AudioSwitchManager.kt +61 -0
  5. package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +14 -0
  6. package/android/src/main/java/io/fishjam/reactnative/Errors.kt +31 -0
  7. package/android/src/main/java/io/fishjam/reactnative/FishjamForegroundService.kt +90 -0
  8. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +870 -0
  9. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +370 -0
  10. package/android/src/main/java/io/fishjam/reactnative/Utils.kt +11 -0
  11. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewView.kt +40 -0
  12. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewViewModule.kt +17 -0
  13. package/android/src/main/java/io/fishjam/reactnative/VideoRendererView.kt +58 -0
  14. package/android/src/main/java/io/fishjam/reactnative/VideoRendererViewModule.kt +25 -0
  15. package/android/src/main/java/io/fishjam/reactnative/VideoView.kt +77 -0
  16. package/package.json +4 -4
  17. package/plugin/build/types.d.ts +9 -0
  18. package/plugin/build/types.js +2 -0
  19. package/plugin/build/withFishjam.d.ts +4 -0
  20. package/plugin/build/withFishjam.js +13 -0
  21. package/plugin/build/withFishjamAndroid.d.ts +3 -0
  22. package/plugin/build/withFishjamAndroid.js +32 -0
  23. package/plugin/build/withFishjamIos.d.ts +9 -0
  24. package/plugin/build/withFishjamIos.js +222 -0
@@ -0,0 +1,9 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ import { FishjamPluginOptions } from './types';
3
+ export declare const SBE_PODFILE_SNIPPET = "\ntarget 'FishjamScreenBroadcastExtension' do\n pod 'FishjamCloudClient/Broadcast'\nend";
4
+ /**
5
+ * Applies screen sharing plugin if enabled. In order for screensharing to work, we need to copy extension files to your iOS project.
6
+ * Allows for dynamically changing deploymentTarget.
7
+ */
8
+ declare const withFishjamIos: ConfigPlugin<FishjamPluginOptions>;
9
+ export default withFishjamIos;
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.SBE_PODFILE_SNIPPET = void 0;
27
+ // ios-related code was mostly copied from OneSignal expo plugin: https://github.com/OneSignal/onesignal-expo-plugin/blob/main/onesignal/withOneSignalIos.ts
28
+ const config_plugins_1 = require("@expo/config-plugins");
29
+ const fs = __importStar(require("promise-fs"));
30
+ const path = __importStar(require("path"));
31
+ const SBE_TARGET_NAME = 'FishjamScreenBroadcastExtension';
32
+ exports.SBE_PODFILE_SNIPPET = `
33
+ target '${SBE_TARGET_NAME}' do
34
+ pod 'FishjamCloudClient/Broadcast'
35
+ end`;
36
+ const TARGETED_DEVICE_FAMILY = `"1,2"`;
37
+ const IPHONEOS_DEPLOYMENT_TARGET = '13.4';
38
+ const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
39
+ const BUNDLE_IDENTIFIER_TEMPLATE_REGEX = /{{BUNDLE_IDENTIFIER}}/gm;
40
+ /**
41
+ * A helper function for updating a value in a file for given regex
42
+ */
43
+ async function updateFileWithRegex(iosPath, fileName, regex, value) {
44
+ const filePath = `${iosPath}/${SBE_TARGET_NAME}/${fileName}`;
45
+ let file = await fs.readFile(filePath, { encoding: 'utf-8' });
46
+ file = file.replace(regex, value);
47
+ await fs.writeFile(filePath, file);
48
+ }
49
+ /**
50
+ * Inserts a required target to Podfile.
51
+ * This is needed to provide the dependency of FishjamCloudClient/Broadcast to the extension.
52
+ */
53
+ async function updatePodfile(iosPath) {
54
+ let matches;
55
+ try {
56
+ const podfile = await fs.readFile(`${iosPath}/Podfile`, {
57
+ encoding: 'utf-8',
58
+ });
59
+ matches = podfile.match(exports.SBE_PODFILE_SNIPPET);
60
+ }
61
+ catch (e) {
62
+ console.error('Error reading from Podfile: ', e);
63
+ }
64
+ if (matches) {
65
+ console.log(`${SBE_TARGET_NAME} target already added to Podfile. Skipping...`);
66
+ return;
67
+ }
68
+ try {
69
+ fs.appendFile(`${iosPath}/Podfile`, exports.SBE_PODFILE_SNIPPET);
70
+ }
71
+ catch (e) {
72
+ console.error('Error writing to Podfile: ', e);
73
+ }
74
+ }
75
+ /**
76
+ * Adds "App Group" permission
77
+ * App Group allow your app and the FishjamScreenBroadcastExtension to communicate with each other.
78
+ */
79
+ const withAppGroupPermissions = (config) => {
80
+ const APP_GROUP_KEY = 'com.apple.security.application-groups';
81
+ return (0, config_plugins_1.withEntitlementsPlist)(config, (newConfig) => {
82
+ if (!Array.isArray(newConfig.modResults[APP_GROUP_KEY])) {
83
+ newConfig.modResults[APP_GROUP_KEY] = [];
84
+ }
85
+ const modResultsArray = newConfig.modResults[APP_GROUP_KEY];
86
+ const entitlement = `group.${newConfig?.ios?.bundleIdentifier || ''}`;
87
+ if (modResultsArray.indexOf(entitlement) !== -1) {
88
+ return newConfig;
89
+ }
90
+ modResultsArray.push(entitlement);
91
+ return newConfig;
92
+ });
93
+ };
94
+ /**
95
+ * Adds constants to Info.plist
96
+ * In other to dynamically retreive extension's bundleId and group name we need to store it in Info.plist.
97
+ */
98
+ const withInfoPlistConstants = (config) => {
99
+ return (0, config_plugins_1.withInfoPlist)(config, (config) => {
100
+ const bundleIdentifier = config.ios?.bundleIdentifier || '';
101
+ config.modResults['AppGroupName'] = `group.${bundleIdentifier}`;
102
+ config.modResults['ScreencastExtensionBundleId'] =
103
+ `${bundleIdentifier}.${SBE_TARGET_NAME}`;
104
+ return config;
105
+ });
106
+ };
107
+ /**
108
+ * Updates and copies required extension files.
109
+ * Our extension needs to be properly setup inside the XCode project. In order to do that we need to copy the files and update the pbxproj.
110
+ */
111
+ const withFishjamSBE = (config, options) => {
112
+ return (0, config_plugins_1.withXcodeProject)(config, async (props) => {
113
+ const appName = props.modRequest.projectName || '';
114
+ const iosPath = props.modRequest.platformProjectRoot;
115
+ const bundleIdentifier = props.ios?.bundleIdentifier;
116
+ const xcodeProject = props.modResults;
117
+ const pluginDir = require.resolve('@fishjam-cloud/react-native-client/package.json');
118
+ const extensionSourceDir = path.join(pluginDir, '../plugin/broadcastExtensionFiles/');
119
+ await updatePodfile(iosPath);
120
+ const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
121
+ const extFiles = [
122
+ 'FishjamBroadcastSampleHandler.swift',
123
+ `${SBE_TARGET_NAME}.entitlements`,
124
+ `Info.plist`,
125
+ ];
126
+ await xcodeProject.parse(async function (err) {
127
+ if (err) {
128
+ console.error(`Error parsing iOS project: ${JSON.stringify(err)}`);
129
+ return;
130
+ }
131
+ if (xcodeProject.pbxTargetByName(`"${SBE_TARGET_NAME}"`)) {
132
+ console.log(`${SBE_TARGET_NAME} already exists in project. Skipping...`);
133
+ return;
134
+ }
135
+ try {
136
+ // copy extension files
137
+ await fs.mkdir(`${iosPath}/${SBE_TARGET_NAME}`, { recursive: true });
138
+ for (let i = 0; i < extFiles.length; i++) {
139
+ const extFile = extFiles[i];
140
+ const targetFile = `${iosPath}/${SBE_TARGET_NAME}/${extFile}`;
141
+ await fs.copyFile(`${extensionSourceDir}${extFile}`, targetFile);
142
+ }
143
+ }
144
+ catch (e) {
145
+ console.error('Error copying extension files: ', e);
146
+ }
147
+ // update extension files
148
+ await updateFileWithRegex(iosPath, `${SBE_TARGET_NAME}.entitlements`, GROUP_IDENTIFIER_TEMPLATE_REGEX, `group.${bundleIdentifier}`);
149
+ await updateFileWithRegex(iosPath, 'FishjamBroadcastSampleHandler.swift', GROUP_IDENTIFIER_TEMPLATE_REGEX, `group.${bundleIdentifier}`);
150
+ await updateFileWithRegex(iosPath, 'FishjamBroadcastSampleHandler.swift', BUNDLE_IDENTIFIER_TEMPLATE_REGEX, bundleIdentifier || '');
151
+ // Create new PBXGroup for the extension
152
+ const extGroup = xcodeProject.addPbxGroup(extFiles, SBE_TARGET_NAME, SBE_TARGET_NAME);
153
+ // Add the new PBXGroup to the top level group. This makes the
154
+ // files / folder appear in the file explorer in Xcode.
155
+ const groups = xcodeProject.hash.project.objects['PBXGroup'];
156
+ Object.keys(groups).forEach(function (key) {
157
+ if (groups[key].name === undefined) {
158
+ xcodeProject.addToPbxGroup(extGroup.uuid, key);
159
+ }
160
+ });
161
+ // WORK AROUND for codeProject.addTarget BUG
162
+ // Xcode projects don't contain these if there is only one target
163
+ // An upstream fix should be made to the code referenced in this link:
164
+ // - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
165
+ const projObjects = xcodeProject.hash.project.objects;
166
+ projObjects['PBXTargetDependency'] =
167
+ projObjects['PBXTargetDependency'] || {};
168
+ projObjects['PBXContainerItemProxy'] =
169
+ projObjects['PBXTargetDependency'] || {};
170
+ // Add the SBE target
171
+ // This adds PBXTargetDependency and PBXContainerItemProxy for you
172
+ const sbeTarget = xcodeProject.addTarget(SBE_TARGET_NAME, 'app_extension', SBE_TARGET_NAME, `${bundleIdentifier}.${SBE_TARGET_NAME}`);
173
+ // Add build phases to the new target
174
+ xcodeProject.addBuildPhase(['FishjamBroadcastSampleHandler.swift'], 'PBXSourcesBuildPhase', 'Sources', sbeTarget.uuid);
175
+ xcodeProject.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', sbeTarget.uuid);
176
+ xcodeProject.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', sbeTarget.uuid);
177
+ xcodeProject.addFramework('ReplayKit.framework', {
178
+ target: sbeTarget.uuid,
179
+ });
180
+ // Edit the Deployment info of the new Target, only IphoneOS and Targeted Device Family
181
+ // However, can be more
182
+ const configurations = xcodeProject.pbxXCBuildConfigurationSection();
183
+ for (const key in configurations) {
184
+ if (typeof configurations[key].buildSettings !== 'undefined' &&
185
+ configurations[key].buildSettings.PRODUCT_NAME ===
186
+ `"${SBE_TARGET_NAME}"`) {
187
+ const buildSettingsObj = configurations[key].buildSettings;
188
+ buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
189
+ options.ios.iphoneDeploymentTarget ?? IPHONEOS_DEPLOYMENT_TARGET;
190
+ buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
191
+ buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${SBE_TARGET_NAME}/${SBE_TARGET_NAME}.entitlements`;
192
+ buildSettingsObj.CODE_SIGN_STYLE = 'Automatic';
193
+ buildSettingsObj.INFOPLIST_FILE = `${SBE_TARGET_NAME}/Info.plist`;
194
+ buildSettingsObj.SWIFT_VERSION = '5.0';
195
+ buildSettingsObj.MARKETING_VERSION = '1.0.0';
196
+ buildSettingsObj.CURRENT_PROJECT_VERSION = '1';
197
+ buildSettingsObj.ENABLE_BITCODE = 'NO';
198
+ }
199
+ }
200
+ await fs.writeFile(projPath, xcodeProject.writeSync());
201
+ });
202
+ return props;
203
+ });
204
+ };
205
+ /**
206
+ * Applies screen sharing plugin if enabled. In order for screensharing to work, we need to copy extension files to your iOS project.
207
+ * Allows for dynamically changing deploymentTarget.
208
+ */
209
+ const withFishjamIos = (config, props) => {
210
+ if (props.ios.enableScreensharing) {
211
+ withAppGroupPermissions(config);
212
+ withInfoPlistConstants(config);
213
+ withFishjamSBE(config, props);
214
+ }
215
+ (0, config_plugins_1.withPodfileProperties)(config, (config) => {
216
+ config.modResults['ios.deploymentTarget'] =
217
+ props.ios.iphoneDeploymentTarget ?? IPHONEOS_DEPLOYMENT_TARGET;
218
+ return config;
219
+ });
220
+ return config;
221
+ };
222
+ exports.default = withFishjamIos;