@fishjam-cloud/react-native-client 0.18.1 → 0.19.1

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 (61) hide show
  1. package/README.md +1 -1
  2. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +25 -15
  3. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +52 -0
  4. package/build/RNFishjamClientModule.d.ts +6 -1
  5. package/build/RNFishjamClientModule.d.ts.map +1 -1
  6. package/build/RNFishjamClientModule.js.map +1 -1
  7. package/build/components/FishjamRoom/index.d.ts +6 -0
  8. package/build/components/FishjamRoom/index.d.ts.map +1 -1
  9. package/build/components/FishjamRoom/index.js +6 -0
  10. package/build/components/FishjamRoom/index.js.map +1 -1
  11. package/build/components/LivestreamView.d.ts +33 -1
  12. package/build/components/LivestreamView.d.ts.map +1 -1
  13. package/build/components/LivestreamView.js +1 -1
  14. package/build/components/LivestreamView.js.map +1 -1
  15. package/build/components/VideoPreviewView.d.ts +1 -1
  16. package/build/components/VideoPreviewView.js +1 -0
  17. package/build/components/VideoPreviewView.js.map +1 -1
  18. package/build/components/VideoRendererView.d.ts +2 -2
  19. package/build/components/VideoRendererView.js +3 -2
  20. package/build/components/VideoRendererView.js.map +1 -1
  21. package/build/consts/index.d.ts +3 -0
  22. package/build/consts/index.d.ts.map +1 -0
  23. package/build/consts/index.js +4 -0
  24. package/build/consts/index.js.map +1 -0
  25. package/build/debug/stats/useRTCStatistics.js.map +1 -1
  26. package/build/hooks/useCamera.d.ts +5 -5
  27. package/build/hooks/useCamera.js.map +1 -1
  28. package/build/hooks/useConnection.d.ts +18 -7
  29. package/build/hooks/useConnection.d.ts.map +1 -1
  30. package/build/hooks/useConnection.js +10 -2
  31. package/build/hooks/useConnection.js.map +1 -1
  32. package/build/hooks/useMicrophone.d.ts +6 -2
  33. package/build/hooks/useMicrophone.d.ts.map +1 -1
  34. package/build/hooks/useMicrophone.js +12 -2
  35. package/build/hooks/useMicrophone.js.map +1 -1
  36. package/build/hooks/usePeers.js.map +1 -1
  37. package/build/hooks/usePermissions.d.ts +24 -0
  38. package/build/hooks/usePermissions.d.ts.map +1 -0
  39. package/build/hooks/usePermissions.js +61 -0
  40. package/build/hooks/usePermissions.js.map +1 -0
  41. package/build/hooks/useSandbox.d.ts +13 -0
  42. package/build/hooks/useSandbox.d.ts.map +1 -0
  43. package/build/hooks/useSandbox.js +42 -0
  44. package/build/hooks/useSandbox.js.map +1 -0
  45. package/build/hooks/useScreenShare.d.ts +1 -1
  46. package/build/hooks/useScreenShare.js.map +1 -1
  47. package/build/index.d.ts +5 -2
  48. package/build/index.d.ts.map +1 -1
  49. package/build/index.js +3 -0
  50. package/build/index.js.map +1 -1
  51. package/build/types.d.ts +1 -0
  52. package/build/types.d.ts.map +1 -1
  53. package/build/types.js.map +1 -1
  54. package/ios/CameraPermissionsRequester.swift +117 -0
  55. package/ios/RNFishjamClient.swift +31 -20
  56. package/ios/RNFishjamClientModule.swift +176 -119
  57. package/package.json +16 -11
  58. package/plugin/build/types.d.ts +5 -0
  59. package/plugin/build/withFishjamAndroid.js +16 -4
  60. package/plugin/build/withFishjamIos.d.ts +1 -1
  61. package/plugin/build/withFishjamIos.js +106 -48
@@ -33,16 +33,19 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SBE_PODFILE_SNIPPET = void 0;
36
+ exports.getSbePodfileSnippet = getSbePodfileSnippet;
37
37
  // ios-related code was mostly copied from OneSignal expo plugin: https://github.com/OneSignal/onesignal-expo-plugin/blob/main/onesignal/withOneSignalIos.ts
38
38
  const config_plugins_1 = require("@expo/config-plugins");
39
39
  const fs = __importStar(require("promise-fs"));
40
40
  const path = __importStar(require("path"));
41
- const SBE_TARGET_NAME = 'FishjamScreenBroadcastExtension';
42
- exports.SBE_PODFILE_SNIPPET = `
43
- target '${SBE_TARGET_NAME}' do
44
- pod 'FishjamCloudClient/Broadcast'
45
- end`;
41
+ function getSbeTargetName(props) {
42
+ return (props?.ios?.broadcastExtensionTargetName ||
43
+ 'FishjamScreenBroadcastExtension');
44
+ }
45
+ function getSbePodfileSnippet(props) {
46
+ const targetName = getSbeTargetName(props);
47
+ return `\ntarget '${targetName}' do\n pod 'FishjamCloudClient/Broadcast'\nend`;
48
+ }
46
49
  const TARGETED_DEVICE_FAMILY = `"1,2"`;
47
50
  const IPHONEOS_DEPLOYMENT_TARGET = '15.1';
48
51
  const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
@@ -50,8 +53,9 @@ const BUNDLE_IDENTIFIER_TEMPLATE_REGEX = /{{BUNDLE_IDENTIFIER}}/gm;
50
53
  /**
51
54
  * A helper function for updating a value in a file for given regex
52
55
  */
53
- async function updateFileWithRegex(iosPath, fileName, regex, value) {
54
- const filePath = `${iosPath}/${SBE_TARGET_NAME}/${fileName}`;
56
+ async function updateFileWithRegex(iosPath, fileName, regex, value, props) {
57
+ const targetName = getSbeTargetName(props);
58
+ const filePath = `${iosPath}/${targetName}/${fileName}`;
55
59
  let file = await fs.readFile(filePath, { encoding: 'utf-8' });
56
60
  file = file.replace(regex, value);
57
61
  await fs.writeFile(filePath, file);
@@ -60,23 +64,24 @@ async function updateFileWithRegex(iosPath, fileName, regex, value) {
60
64
  * Inserts a required target to Podfile.
61
65
  * This is needed to provide the dependency of FishjamCloudClient/Broadcast to the extension.
62
66
  */
63
- async function updatePodfile(iosPath) {
67
+ async function updatePodfile(iosPath, props) {
68
+ const podfileSnippet = getSbePodfileSnippet(props);
64
69
  let matches;
65
70
  try {
66
71
  const podfile = await fs.readFile(`${iosPath}/Podfile`, {
67
72
  encoding: 'utf-8',
68
73
  });
69
- matches = podfile.match(exports.SBE_PODFILE_SNIPPET);
74
+ matches = podfile.match(podfileSnippet);
70
75
  }
71
76
  catch (e) {
72
77
  console.error('Error reading from Podfile: ', e);
73
78
  }
74
79
  if (matches) {
75
- console.log(`${SBE_TARGET_NAME} target already added to Podfile. Skipping...`);
80
+ console.log(`${getSbeTargetName(props)} target already added to Podfile. Skipping...`);
76
81
  return;
77
82
  }
78
83
  try {
79
- fs.appendFile(`${iosPath}/Podfile`, exports.SBE_PODFILE_SNIPPET);
84
+ fs.appendFile(`${iosPath}/Podfile`, podfileSnippet);
80
85
  }
81
86
  catch (e) {
82
87
  console.error('Error writing to Podfile: ', e);
@@ -86,30 +91,69 @@ async function updatePodfile(iosPath) {
86
91
  * Adds "App Group" permission
87
92
  * App Group allow your app and the FishjamScreenBroadcastExtension to communicate with each other.
88
93
  */
89
- const withAppGroupPermissions = (config) => {
94
+ const withAppGroupPermissions = (config, props) => {
90
95
  const APP_GROUP_KEY = 'com.apple.security.application-groups';
91
- return (0, config_plugins_1.withEntitlementsPlist)(config, (newConfig) => {
92
- if (!Array.isArray(newConfig.modResults[APP_GROUP_KEY])) {
93
- newConfig.modResults[APP_GROUP_KEY] = [];
94
- }
95
- const modResultsArray = newConfig.modResults[APP_GROUP_KEY];
96
- const entitlement = `group.${newConfig?.ios?.bundleIdentifier || ''}`;
97
- if (modResultsArray.indexOf(entitlement) !== -1) {
98
- return newConfig;
96
+ const bundleIdentifier = config.ios?.bundleIdentifier || '';
97
+ const groupIdentifier = props?.ios?.appGroupContainerId || `group.${bundleIdentifier}`;
98
+ const mainTarget = props?.ios?.mainTargetName || '';
99
+ config.ios ??= {};
100
+ config.ios.entitlements ??= {};
101
+ config.ios.entitlements[APP_GROUP_KEY] ??= [];
102
+ const entitlementsArray = config.ios.entitlements[APP_GROUP_KEY];
103
+ if (!entitlementsArray.includes(groupIdentifier)) {
104
+ entitlementsArray.push(groupIdentifier);
105
+ }
106
+ config = (0, config_plugins_1.withEntitlementsPlist)(config, (newConfig) => {
107
+ const modResultsArray = newConfig.modResults[APP_GROUP_KEY] || [];
108
+ if (!modResultsArray.includes(groupIdentifier)) {
109
+ modResultsArray.push(groupIdentifier);
99
110
  }
100
- modResultsArray.push(entitlement);
111
+ newConfig.modResults[APP_GROUP_KEY] = modResultsArray;
101
112
  return newConfig;
102
113
  });
114
+ config = (0, config_plugins_1.withXcodeProject)(config, (props) => {
115
+ const xcodeProject = props.modResults;
116
+ const targets = xcodeProject.getFirstTarget();
117
+ const project = xcodeProject.getFirstProject();
118
+ if (!targets || !project) {
119
+ return props;
120
+ }
121
+ const targetUuid = targets.uuid;
122
+ const projectUuid = project.uuid;
123
+ const projectObj = xcodeProject.hash.project.objects.PBXProject[projectUuid];
124
+ projectObj.attributes ??= {};
125
+ projectObj.attributes.TargetAttributes ??= {};
126
+ projectObj.attributes.TargetAttributes[targetUuid] ??= {};
127
+ projectObj.attributes.TargetAttributes[targetUuid].SystemCapabilities ??=
128
+ {};
129
+ projectObj.attributes.TargetAttributes[targetUuid].SystemCapabilities['com.apple.ApplicationGroups.iOS'] = {
130
+ enabled: 1,
131
+ };
132
+ const mainTargetName = mainTarget || props.modRequest.projectName;
133
+ const entitlementsFilePath = `${mainTargetName}/${mainTargetName}.entitlements`;
134
+ const configurations = xcodeProject.pbxXCBuildConfigurationSection();
135
+ Object.keys(configurations).forEach((key) => {
136
+ const config = configurations[key];
137
+ if (config.buildSettings?.PRODUCT_NAME?.includes(mainTargetName)) {
138
+ if (!config.buildSettings.CODE_SIGN_ENTITLEMENTS) {
139
+ config.buildSettings.CODE_SIGN_ENTITLEMENTS = entitlementsFilePath;
140
+ }
141
+ }
142
+ });
143
+ return props;
144
+ });
145
+ return config;
103
146
  };
104
147
  /**
105
148
  * Adds constants to Info.plist
106
149
  * In other to dynamically retreive extension's bundleId and group name we need to store it in Info.plist.
107
150
  */
108
- const withInfoPlistConstants = (config) => (0, config_plugins_1.withInfoPlist)(config, (configuration) => {
151
+ const withInfoPlistConstants = (config, props) => (0, config_plugins_1.withInfoPlist)(config, (configuration) => {
109
152
  const bundleIdentifier = configuration.ios?.bundleIdentifier || '';
110
- configuration.modResults['AppGroupName'] = `group.${bundleIdentifier}`;
153
+ const groupIdentifier = props?.ios?.appGroupContainerId || `group.${bundleIdentifier}`;
154
+ configuration.modResults['AppGroupName'] = groupIdentifier;
111
155
  configuration.modResults['ScreenShareExtensionBundleId'] =
112
- `${bundleIdentifier}.${SBE_TARGET_NAME}`;
156
+ `${bundleIdentifier}.${getSbeTargetName(props)}`;
113
157
  return configuration;
114
158
  });
115
159
  /**
@@ -120,14 +164,22 @@ const withFishjamSBE = (config, options) => (0, config_plugins_1.withXcodeProjec
120
164
  const appName = props.modRequest.projectName || '';
121
165
  const iosPath = props.modRequest.platformProjectRoot;
122
166
  const bundleIdentifier = props.ios?.bundleIdentifier;
167
+ const groupIdentifier = options?.ios?.appGroupContainerId || `group.${bundleIdentifier}`;
123
168
  const xcodeProject = props.modResults;
169
+ const targetName = getSbeTargetName(options);
124
170
  const pluginDir = require.resolve('@fishjam-cloud/react-native-client/package.json');
125
171
  const extensionSourceDir = path.join(pluginDir, '../plugin/broadcastExtensionFiles/');
126
- await updatePodfile(iosPath);
172
+ await updatePodfile(iosPath, options);
127
173
  const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
174
+ const templateTargetName = 'FishjamScreenBroadcastExtension';
128
175
  const extFiles = [
129
176
  'FishjamBroadcastSampleHandler.swift',
130
- `${SBE_TARGET_NAME}.entitlements`,
177
+ `${templateTargetName}.entitlements`,
178
+ `Info.plist`,
179
+ ];
180
+ const destFiles = [
181
+ 'FishjamBroadcastSampleHandler.swift',
182
+ `${targetName}.entitlements`,
131
183
  `Info.plist`,
132
184
  ];
133
185
  await xcodeProject.parse(async function (err) {
@@ -135,28 +187,26 @@ const withFishjamSBE = (config, options) => (0, config_plugins_1.withXcodeProjec
135
187
  console.error(`Error parsing iOS project: ${JSON.stringify(err)}`);
136
188
  return;
137
189
  }
138
- if (xcodeProject.pbxTargetByName(SBE_TARGET_NAME)) {
139
- console.log(`${SBE_TARGET_NAME} already exists in project. Skipping...`);
190
+ if (xcodeProject.pbxTargetByName(targetName)) {
191
+ console.log(`${targetName} already exists in project. Skipping...`);
140
192
  return;
141
193
  }
142
194
  try {
143
- // copy extension files
144
- await fs.mkdir(`${iosPath}/${SBE_TARGET_NAME}`, { recursive: true });
195
+ await fs.mkdir(`${iosPath}/${targetName}`, { recursive: true });
145
196
  for (let i = 0; i < extFiles.length; i++) {
146
- const extFile = extFiles[i];
147
- const targetFile = `${iosPath}/${SBE_TARGET_NAME}/${extFile}`;
148
- await fs.copyFile(`${extensionSourceDir}${extFile}`, targetFile);
197
+ const srcFile = `${extensionSourceDir}${extFiles[i]}`;
198
+ const destFile = `${iosPath}/${targetName}/${destFiles[i]}`;
199
+ await fs.copyFile(srcFile, destFile);
149
200
  }
150
201
  }
151
202
  catch (e) {
152
203
  console.error('Error copying extension files: ', e);
153
204
  }
154
- // update extension files
155
- await updateFileWithRegex(iosPath, `${SBE_TARGET_NAME}.entitlements`, GROUP_IDENTIFIER_TEMPLATE_REGEX, `group.${bundleIdentifier}`);
156
- await updateFileWithRegex(iosPath, 'FishjamBroadcastSampleHandler.swift', GROUP_IDENTIFIER_TEMPLATE_REGEX, `group.${bundleIdentifier}`);
157
- await updateFileWithRegex(iosPath, 'FishjamBroadcastSampleHandler.swift', BUNDLE_IDENTIFIER_TEMPLATE_REGEX, bundleIdentifier || '');
205
+ await updateFileWithRegex(iosPath, `${targetName}.entitlements`, GROUP_IDENTIFIER_TEMPLATE_REGEX, groupIdentifier, options);
206
+ await updateFileWithRegex(iosPath, 'FishjamBroadcastSampleHandler.swift', GROUP_IDENTIFIER_TEMPLATE_REGEX, groupIdentifier, options);
207
+ await updateFileWithRegex(iosPath, 'FishjamBroadcastSampleHandler.swift', BUNDLE_IDENTIFIER_TEMPLATE_REGEX, bundleIdentifier || '', options);
158
208
  // Create new PBXGroup for the extension
159
- const extGroup = xcodeProject.addPbxGroup(extFiles, SBE_TARGET_NAME, SBE_TARGET_NAME);
209
+ const extGroup = xcodeProject.addPbxGroup(extFiles, targetName, targetName);
160
210
  // Add the new PBXGroup to the top level group. This makes the
161
211
  // files / folder appear in the file explorer in Xcode.
162
212
  const groups = xcodeProject.hash.project.objects['PBXGroup'];
@@ -176,7 +226,7 @@ const withFishjamSBE = (config, options) => (0, config_plugins_1.withXcodeProjec
176
226
  projObjects['PBXTargetDependency'] || {};
177
227
  // Add the SBE target
178
228
  // This adds PBXTargetDependency and PBXContainerItemProxy for you
179
- const sbeTarget = xcodeProject.addTarget(SBE_TARGET_NAME, 'app_extension', SBE_TARGET_NAME, `${bundleIdentifier}.${SBE_TARGET_NAME}`);
229
+ const sbeTarget = xcodeProject.addTarget(targetName, 'app_extension', targetName, `${bundleIdentifier}.${targetName}`);
180
230
  // Add build phases to the new target
181
231
  xcodeProject.addBuildPhase(['FishjamBroadcastSampleHandler.swift'], 'PBXSourcesBuildPhase', 'Sources', sbeTarget.uuid);
182
232
  xcodeProject.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', sbeTarget.uuid);
@@ -189,15 +239,14 @@ const withFishjamSBE = (config, options) => (0, config_plugins_1.withXcodeProjec
189
239
  const configurations = xcodeProject.pbxXCBuildConfigurationSection();
190
240
  for (const key in configurations) {
191
241
  if (typeof configurations[key].buildSettings !== 'undefined' &&
192
- configurations[key].buildSettings.PRODUCT_NAME ===
193
- `"${SBE_TARGET_NAME}"`) {
242
+ configurations[key].buildSettings.PRODUCT_NAME === `"${targetName}"`) {
194
243
  const buildSettingsObj = configurations[key].buildSettings;
195
244
  buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
196
245
  options?.ios?.iphoneDeploymentTarget ?? IPHONEOS_DEPLOYMENT_TARGET;
197
246
  buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
198
- buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${SBE_TARGET_NAME}/${SBE_TARGET_NAME}.entitlements`;
247
+ buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${targetName}/${targetName}.entitlements`;
199
248
  buildSettingsObj.CODE_SIGN_STYLE = 'Automatic';
200
- buildSettingsObj.INFOPLIST_FILE = `${SBE_TARGET_NAME}/Info.plist`;
249
+ buildSettingsObj.INFOPLIST_FILE = `${targetName}/Info.plist`;
201
250
  buildSettingsObj.SWIFT_VERSION = '5.0';
202
251
  buildSettingsObj.MARKETING_VERSION = '1.0.0';
203
252
  buildSettingsObj.CURRENT_PROJECT_VERSION = '1';
@@ -208,21 +257,30 @@ const withFishjamSBE = (config, options) => (0, config_plugins_1.withXcodeProjec
208
257
  });
209
258
  return props;
210
259
  });
260
+ const withFishjamPictureInPicture = (config, props) => (0, config_plugins_1.withInfoPlist)(config, (configuration) => {
261
+ if (props?.ios?.supportsPictureInPicture) {
262
+ const backgroundModes = new Set(configuration.modResults.UIBackgroundModes ?? []);
263
+ backgroundModes.add('audio');
264
+ configuration.modResults.UIBackgroundModes = Array.from(backgroundModes);
265
+ }
266
+ return configuration;
267
+ });
211
268
  /**
212
269
  * Applies screen sharing plugin if enabled. In order for screensharing to work, we need to copy extension files to your iOS project.
213
270
  * Allows for dynamically changing deploymentTarget.
214
271
  */
215
272
  const withFishjamIos = (config, props) => {
216
273
  if (props?.ios?.enableScreensharing) {
217
- withAppGroupPermissions(config);
218
- withInfoPlistConstants(config);
219
- withFishjamSBE(config, props);
274
+ config = withAppGroupPermissions(config, props);
275
+ config = withInfoPlistConstants(config, props);
276
+ config = withFishjamSBE(config, props);
220
277
  }
221
- (0, config_plugins_1.withPodfileProperties)(config, (configuration) => {
278
+ config = (0, config_plugins_1.withPodfileProperties)(config, (configuration) => {
222
279
  configuration.modResults['ios.deploymentTarget'] =
223
280
  props?.ios?.iphoneDeploymentTarget ?? IPHONEOS_DEPLOYMENT_TARGET;
224
281
  return configuration;
225
282
  });
283
+ config = withFishjamPictureInPicture(config, props);
226
284
  return config;
227
285
  };
228
286
  exports.default = withFishjamIos;