react-native-legal 1.6.5 → 1.8.0

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 (38) hide show
  1. package/Package.swift +56 -0
  2. package/android/build.gradle +44 -30
  3. package/android/src/main/java/com/reactnativelegal/ReactNativeLegalActivity.kt +73 -76
  4. package/android/src/main/java/com/reactnativelegal/ReactNativeLegalModuleImpl.kt +24 -6
  5. package/android/src/main/res/layout/activity_licenses.xml +4 -26
  6. package/android/src/main/res/values/styles.xml +1 -3
  7. package/bare-plugin/build/android/addListActivity.js +2 -2
  8. package/bare-plugin/build/android/addResourceKeepFile.d.ts +4 -0
  9. package/bare-plugin/build/android/addResourceKeepFile.js +10 -0
  10. package/bare-plugin/build/android/androidCommand.js +2 -0
  11. package/bare-plugin/build/android/applyAndConfigureAboutLibrariesPlugin.js +5 -5
  12. package/bare-plugin/build/android/declareAboutLibrariesPlugin.js +5 -5
  13. package/bare-plugin/src/android/addListActivity.ts +1 -1
  14. package/bare-plugin/src/android/addResourceKeepFile.ts +8 -0
  15. package/bare-plugin/src/android/androidCommand.ts +2 -0
  16. package/bare-plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts +2 -2
  17. package/bare-plugin/src/android/declareAboutLibrariesPlugin.ts +2 -2
  18. package/bare-plugin/tsconfig.json +4 -3
  19. package/ios/ReactNativeLegalDetailViewController.swift +2 -0
  20. package/ios/ReactNativeLegalModule.mm +12 -1
  21. package/ios/ReactNativeLegalModuleImpl.swift +5 -2
  22. package/ios/ReactNativeLegalTableViewController.swift +2 -0
  23. package/package.json +4 -1
  24. package/plugin/build/android/addResourceKeepFile.d.ts +5 -0
  25. package/plugin/build/android/addResourceKeepFile.js +17 -0
  26. package/plugin/build/android/withAndroidLegal.js +2 -0
  27. package/plugin/src/android/addResourceKeepFile.ts +17 -0
  28. package/plugin/src/android/withAndroidLegal.ts +2 -0
  29. package/plugin-utils/build/android.d.ts +4 -0
  30. package/plugin-utils/build/android.js +82 -23
  31. package/plugin-utils/build/ios.js +13 -3
  32. package/plugin-utils/src/android.ts +99 -27
  33. package/plugin-utils/src/ios.ts +19 -3
  34. package/plugin-utils/tsconfig.json +5 -4
  35. package/swift-tools/Package.resolved +96 -0
  36. package/swift-tools/Package.swift +15 -0
  37. package/android/src/main/res/values/colors.xml +0 -3
  38. package/android/src/main/res/values-night/colors.xml +0 -3
@@ -1,11 +1,19 @@
1
1
  #import "ReactNativeLegalModule.h"
2
2
 
3
+ #import <React/RCTUtils.h>
4
+
5
+ #ifdef REACT_NATIVE_LEGAL_USING_SPM
6
+ @import ReactNativeLegalSwift;
7
+ #else
8
+
3
9
  #if __has_include(<ReactNativeLegal/ReactNativeLegal-Swift.h>)
4
10
  #import <ReactNativeLegal/ReactNativeLegal-Swift.h>
5
11
  #else
6
12
  #import "ReactNativeLegal-Swift.h"
7
13
  #endif
8
14
 
15
+ #endif
16
+
9
17
  #if RCT_NEW_ARCH_ENABLED
10
18
  #import "ReactNativeLegal.h"
11
19
 
@@ -19,7 +27,10 @@ RCT_EXPORT_MODULE(ReactNativeLegalModule)
19
27
 
20
28
  RCT_EXPORT_METHOD(launchLicenseListScreen : (NSString *)licenseHeaderText)
21
29
  {
22
- [ReactNativeLegalModuleImpl launchLicenseListScreenWithLicenseHeaderText:licenseHeaderText];
30
+ [ReactNativeLegalModuleImpl launchLicenseListScreenWithLicenseHeaderText:licenseHeaderText
31
+ getPresentedViewController:^{
32
+ return RCTPresentedViewController();
33
+ }];
23
34
  }
24
35
 
25
36
  RCT_EXPORT_METHOD(getLibrariesAsync : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject)
@@ -2,7 +2,10 @@ import UIKit
2
2
 
3
3
  @objc(ReactNativeLegalModuleImpl)
4
4
  public class ReactNativeLegalModuleImpl: NSObject {
5
- @objc public static func launchLicenseListScreen(licenseHeaderText: String) {
5
+ @objc public static func launchLicenseListScreen(
6
+ licenseHeaderText: String,
7
+ getPresentedViewController: @Sendable @escaping () -> UIViewController?
8
+ ) {
6
9
  guard
7
10
  let settingsBundleUrl = Bundle.main.url(forResource: "Settings", withExtension: "bundle"),
8
11
  let settingsBundle = Bundle(url: settingsBundleUrl),
@@ -19,7 +22,7 @@ public class ReactNativeLegalModuleImpl: NSObject {
19
22
  )
20
23
 
21
24
  DispatchQueue.main.async {
22
- guard let presentedViewController = RCTPresentedViewController() else {
25
+ guard let presentedViewController = getPresentedViewController() else {
23
26
  return
24
27
  }
25
28
 
@@ -1,3 +1,5 @@
1
+ import UIKit
2
+
1
3
  class ReactNativeLegalTableViewController: UITableViewController {
2
4
  private let cellIdentifier = "ReactNativeLegalCell"
3
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-legal",
3
- "version": "1.6.5",
3
+ "version": "1.8.0",
4
4
  "description": "Acknowledge OSS libraries used in your React Native app",
5
5
  "keywords": [
6
6
  "react-native",
@@ -37,8 +37,11 @@
37
37
  "plugin",
38
38
  "plugin-utils",
39
39
  "src",
40
+ "swift-tools/Package.resolved",
41
+ "swift-tools/Package.swift",
40
42
  "LICENSE",
41
43
  "app.plugin.js",
44
+ "Package.swift",
42
45
  "react-native.config.js",
43
46
  "ReactNativeLegal.podspec"
44
47
  ],
@@ -0,0 +1,5 @@
1
+ import type { ExpoConfig } from 'expo/config';
2
+ /**
3
+ * Adds a file that will keep the About Libraries json resource when resource shrinking is enabled
4
+ */
5
+ export declare function addResourceKeepFile(config: ExpoConfig): ExpoConfig;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addResourceKeepFile = addResourceKeepFile;
4
+ const config_plugins_1 = require("expo/config-plugins");
5
+ const android_1 = require("../../../plugin-utils/build/android");
6
+ /**
7
+ * Adds a file that will keep the About Libraries json resource when resource shrinking is enabled
8
+ */
9
+ function addResourceKeepFile(config) {
10
+ return (0, config_plugins_1.withDangerousMod)(config, [
11
+ 'android',
12
+ (exportedConfig) => {
13
+ (0, android_1.addResourceKeepFileUtil)(exportedConfig.modRequest.platformProjectRoot);
14
+ return exportedConfig;
15
+ },
16
+ ]);
17
+ }
@@ -8,6 +8,7 @@ const node_path_1 = __importDefault(require("node:path"));
8
8
  const licenses_1 = require("@callstack/licenses");
9
9
  const config_plugins_1 = require("expo/config-plugins");
10
10
  const addListActivity_1 = require("./addListActivity");
11
+ const addResourceKeepFile_1 = require("./addResourceKeepFile");
11
12
  const applyAndConfigureAboutLibrariesPlugin_1 = require("./applyAndConfigureAboutLibrariesPlugin");
12
13
  const declareAboutLibrariesPlugin_1 = require("./declareAboutLibrariesPlugin");
13
14
  /**
@@ -25,6 +26,7 @@ const withAndroidLegal = (config, { scanOptionsFactory }) => {
25
26
  config = (0, declareAboutLibrariesPlugin_1.declareAboutLibrariesPlugin)(config);
26
27
  config = (0, applyAndConfigureAboutLibrariesPlugin_1.applyAndConfigureAboutLibrariesPlugin)(config);
27
28
  config = (0, addListActivity_1.addListActivity)(config);
29
+ config = (0, addResourceKeepFile_1.addResourceKeepFile)(config);
28
30
  return config;
29
31
  };
30
32
  exports.withAndroidLegal = withAndroidLegal;
@@ -0,0 +1,17 @@
1
+ import type { ExpoConfig } from 'expo/config';
2
+ import { withDangerousMod } from 'expo/config-plugins';
3
+
4
+ import { addResourceKeepFileUtil } from '../../../plugin-utils/build/android';
5
+
6
+ /**
7
+ * Adds a file that will keep the About Libraries json resource when resource shrinking is enabled
8
+ */
9
+ export function addResourceKeepFile(config: ExpoConfig): ExpoConfig {
10
+ return withDangerousMod(config, [
11
+ 'android',
12
+ (exportedConfig) => {
13
+ addResourceKeepFileUtil(exportedConfig.modRequest.platformProjectRoot);
14
+ return exportedConfig;
15
+ },
16
+ ]);
17
+ }
@@ -6,6 +6,7 @@ import { type ConfigPlugin, withAndroidManifest } from 'expo/config-plugins';
6
6
  import type { PlatformPluginOptions } from '../types';
7
7
 
8
8
  import { addListActivity } from './addListActivity';
9
+ import { addResourceKeepFile } from './addResourceKeepFile';
9
10
  import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin';
10
11
  import { declareAboutLibrariesPlugin } from './declareAboutLibrariesPlugin';
11
12
 
@@ -28,5 +29,6 @@ export const withAndroidLegal: ConfigPlugin<PlatformPluginOptions> = (config, {
28
29
  config = declareAboutLibrariesPlugin(config);
29
30
  config = applyAndConfigureAboutLibrariesPlugin(config);
30
31
  config = addListActivity(config);
32
+ config = addResourceKeepFile(config);
31
33
  return config;
32
34
  };
@@ -10,3 +10,7 @@ export declare function applyAndConfigureAboutLibrariesPluginUtil(androidAppBuil
10
10
  * adds a list activity to the list of application's activities
11
11
  */
12
12
  export declare function addListActivityUtil<T>(activities: T[]): T[];
13
+ /**
14
+ * adds a file that will keep the About Libraries json resource when resource shrinking is enabled
15
+ */
16
+ export declare function addResourceKeepFileUtil(androidProjectRootDir: string): void;
@@ -1,53 +1,95 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.declareAboutLibrariesPluginUtil = declareAboutLibrariesPluginUtil;
4
7
  exports.applyAndConfigureAboutLibrariesPluginUtil = applyAndConfigureAboutLibrariesPluginUtil;
5
8
  exports.addListActivityUtil = addListActivityUtil;
9
+ exports.addResourceKeepFileUtil = addResourceKeepFileUtil;
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ const node_path_1 = __importDefault(require("node:path"));
6
12
  const licenses_1 = require("@callstack/licenses");
13
+ const ANDROID_PLUGIN_APPLY_BLOCK_IDENTIFIER = 'com.mikepenz.aboutlibraries.plugin.android';
14
+ const ANDROID_PLUGIN_APPLY_BLOCK = `apply plugin: "${ANDROID_PLUGIN_APPLY_BLOCK_IDENTIFIER}"`;
15
+ const ANDROID_PLUGIN_CLASSPATH = 'com.mikepenz.aboutlibraries.plugin.android:com.mikepenz.aboutlibraries.plugin.android.gradle.plugin';
16
+ const ANDROID_PLUGIN_DEFAULT_VERSION = '13.1.0';
17
+ const GRADLE_PLUGIN_PORTAL = 'gradlePluginPortal()';
18
+ const PLUGIN_APPLY_BLOCK_IDENTIFIER = 'com.mikepenz.aboutlibraries.plugin';
19
+ const OLD_PLUGIN_CLASSPATH = 'com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin';
20
+ const OLD_PLUGIN_CLASSPATH_REGEX = new RegExp(`\\s+classpath\\(['"]${OLD_PLUGIN_CLASSPATH}:\\d+\\.\\d+\\.\\d+['"]\\)\\n`);
21
+ const DEPENDENCIES_BLOCK_DECLARATION_REGEX = new RegExp('dependencies\\s*{');
22
+ const REPOSITORIES_BLOCK_DECLARATION_REGEX = new RegExp('repositories\\s*{');
23
+ const APPLY_PLUGIN_BLOCK_REGEX = new RegExp(`apply\\s+plugin:\\s+['"]${PLUGIN_APPLY_BLOCK_IDENTIFIER}['"]\\n`);
24
+ const APPLY_ANDROID_PLUGIN_BLOCK_REGEX = new RegExp(`apply\\s+plugin:\\s+['"]${ANDROID_PLUGIN_APPLY_BLOCK_IDENTIFIER}['"]`);
25
+ const OLD_PLUGIN_CONFIG_BLOCK_REGEX = new RegExp('(?:\\s*aboutLibraries\\s*{\\s+)(?:(?:\\S+\\s*=\\s*\\S+\\s+)*)(?:})');
26
+ const NEW_PLUGIN_CONFIG_GENERATED_START_COMMENT = '// GENERATED BY REACT-NATIVE-LEGAL DO NOT EDIT!\n';
27
+ const NEW_PLUGIN_CONFIG_GENERATED_END_COMMENT = '// END OF GENERATED BY REACT-NATIVE-LEGAL\n';
28
+ const NEW_PLUGIN_CONFIG_REGEX = new RegExp('(?:\\/\\/ GENERATED BY REACT-NATIVE-LEGAL DO NOT EDIT!\\n)(?:[\\s\\S]+)(?:\\/\\/ END OF GENERATED BY REACT-NATIVE-LEGAL\\n)');
7
29
  /**
8
30
  * Applies Gradle Plugin Portal & AboutLibraries Gradle plugin repositories (if needed) inside root build.gradle
9
31
  */
10
32
  function declareAboutLibrariesPluginUtil(androidBuildGradleContent) {
11
- if (!androidBuildGradleContent.match(PLUGIN_CLASSPATH)?.length) {
12
- // Add Gradle Plugin Portal repository if it's not included
13
- if (!androidBuildGradleContent.match(GRADLE_PLUGIN_PORTAL_URL)?.length) {
14
- androidBuildGradleContent = androidBuildGradleContent.replace(/repositories\s?{/, `repositories {\n maven { url = uri("${GRADLE_PLUGIN_PORTAL_URL}") }`);
15
- console.log('Gradle Plugin Portal repository - ADDED');
16
- }
17
- else {
18
- console.log('Gradle Plugin Portal repository already added - SKIP');
19
- }
33
+ if (androidBuildGradleContent.match(OLD_PLUGIN_CLASSPATH)?.length) {
34
+ // Remove old plugin
35
+ androidBuildGradleContent = androidBuildGradleContent.replace(OLD_PLUGIN_CLASSPATH_REGEX, '');
36
+ }
37
+ if (!androidBuildGradleContent.match(ANDROID_PLUGIN_CLASSPATH)?.length) {
20
38
  // Declare the AboutLibraries plugin
21
- androidBuildGradleContent = androidBuildGradleContent.replace(/dependencies\s?{/, `dependencies {\n classpath("${PLUGIN_CLASSPATH}:${PLUGIN_VERSION}")`);
39
+ androidBuildGradleContent = androidBuildGradleContent.replace(DEPENDENCIES_BLOCK_DECLARATION_REGEX, `dependencies {\n classpath("${ANDROID_PLUGIN_CLASSPATH}:${ANDROID_PLUGIN_DEFAULT_VERSION}")`);
22
40
  console.log('About Libraries Gradle Plugin repository - ADDED');
23
41
  }
24
42
  else {
25
43
  console.log('About Libraries Gradle Plugin already added - SKIP');
26
44
  }
45
+ if (androidBuildGradleContent.match(GRADLE_PLUGIN_PORTAL_URL)?.length) {
46
+ console.log('Gradle Plugin Portal repository already added - SKIP');
47
+ }
48
+ else if (!androidBuildGradleContent.match(GRADLE_PLUGIN_PORTAL)?.length) {
49
+ // Add Gradle Plugin Portal repository if it's not included
50
+ androidBuildGradleContent = androidBuildGradleContent.replace(REPOSITORIES_BLOCK_DECLARATION_REGEX, 'repositories {\n gradlePluginPortal()');
51
+ console.log('Gradle Plugin Portal repository - ADDED');
52
+ }
27
53
  return androidBuildGradleContent;
28
54
  }
29
55
  /**
30
56
  * Applies and configures AboutLibraries Grale plugin (if needed) inside app's build.gradle
31
57
  */
32
58
  function applyAndConfigureAboutLibrariesPluginUtil(androidAppBuildGradleContent) {
33
- // Apply plugin
34
- const applyPluginBlockRegex = new RegExp(`apply\\s+plugin:\\s+['"]${PLUGIN_APPLY_BLOCK_IDENTIFIER}['"]`);
35
- if (!androidAppBuildGradleContent.match(applyPluginBlockRegex)?.length) {
36
- androidAppBuildGradleContent += `\n${PLUGIN_APPLY_BLOCK}`;
59
+ if (androidAppBuildGradleContent.match(APPLY_PLUGIN_BLOCK_REGEX)?.length) {
60
+ // Remove old plugin
61
+ androidAppBuildGradleContent = androidAppBuildGradleContent.replace(APPLY_PLUGIN_BLOCK_REGEX, '');
62
+ }
63
+ // Remove old configuration
64
+ androidAppBuildGradleContent = androidAppBuildGradleContent.replace(OLD_PLUGIN_CONFIG_BLOCK_REGEX, '');
65
+ if (!androidAppBuildGradleContent.match(APPLY_ANDROID_PLUGIN_BLOCK_REGEX)?.length) {
66
+ // Apply plugin
67
+ androidAppBuildGradleContent += `\n${ANDROID_PLUGIN_APPLY_BLOCK}\n`;
37
68
  console.log('About Libraries Gradle Plugin - APPLIED');
38
69
  }
39
70
  else {
40
71
  console.log('About Libraries Gradle Plugin already applied - SKIP');
41
72
  }
73
+ let aboutLibrariesConfig = '\n';
74
+ aboutLibrariesConfig += NEW_PLUGIN_CONFIG_GENERATED_START_COMMENT;
75
+ aboutLibrariesConfig += 'aboutLibraries {\n';
76
+ aboutLibrariesConfig += ' offlineMode = false\n';
77
+ aboutLibrariesConfig += ' collect.configPath = file("../config")\n';
78
+ aboutLibrariesConfig += ' collect.fetchRemoteLicense = false\n';
79
+ aboutLibrariesConfig += ' collect.fetchRemoteFunding = false\n';
80
+ aboutLibrariesConfig += ' export {\n';
81
+ aboutLibrariesConfig += ' prettyPrint = true\n';
82
+ aboutLibrariesConfig += ' }\n';
83
+ aboutLibrariesConfig += '}\n';
84
+ aboutLibrariesConfig += NEW_PLUGIN_CONFIG_GENERATED_END_COMMENT;
42
85
  // Configure plugin
43
- const pluginConfigRegex = /aboutLibraries {/;
44
- if (!androidAppBuildGradleContent.match(pluginConfigRegex)?.length) {
45
- androidAppBuildGradleContent += '\n\naboutLibraries {\n configPath = "config"\n prettyPrint = true\n}\n';
46
- console.log('About Libraries Gradle Plugin - CONFIGURED');
86
+ if (androidAppBuildGradleContent.match(NEW_PLUGIN_CONFIG_REGEX)?.length) {
87
+ androidAppBuildGradleContent = androidAppBuildGradleContent.replace(NEW_PLUGIN_CONFIG_REGEX, aboutLibrariesConfig);
47
88
  }
48
89
  else {
49
- console.log('About Libraries Gradle Plugin already configured - SKIP');
90
+ androidAppBuildGradleContent += aboutLibrariesConfig;
50
91
  }
92
+ console.log('About Libraries Gradle Plugin - CONFIGURED');
51
93
  return androidAppBuildGradleContent;
52
94
  }
53
95
  /**
@@ -82,9 +124,26 @@ function prepareListActivity() {
82
124
  },
83
125
  };
84
126
  }
127
+ const RESOURCE_KEEP_FILE_CONTENT = `<?xml version="1.0" encoding="utf-8"?>
128
+ <resources xmlns:tools="http://schemas.android.com/tools"
129
+ tools:keep="@raw/aboutlibraries" />
130
+ `;
131
+ /**
132
+ * adds a file that will keep the About Libraries json resource when resource shrinking is enabled
133
+ */
134
+ function addResourceKeepFileUtil(androidProjectRootDir) {
135
+ const rawResourcesDir = node_path_1.default.join(androidProjectRootDir, 'app/src/main/res/raw');
136
+ const keepFilePath = node_path_1.default.join(rawResourcesDir, 'com_reactnativelegal_keep.xml');
137
+ if (!node_fs_1.default.existsSync(rawResourcesDir)) {
138
+ node_fs_1.default.mkdirSync(rawResourcesDir, { recursive: true });
139
+ }
140
+ if (!node_fs_1.default.existsSync(keepFilePath)) {
141
+ node_fs_1.default.writeFileSync(keepFilePath, RESOURCE_KEEP_FILE_CONTENT);
142
+ console.log('Android resource keep file - ADDED');
143
+ }
144
+ else {
145
+ console.log('Android resource keep file already exists - SKIPPED');
146
+ }
147
+ }
85
148
  const GRADLE_PLUGIN_PORTAL_URL = 'https://plugins.gradle.org/m2';
86
149
  const PLUGIN_ACTIVITY = 'com.reactnativelegal.ReactNativeLegalActivity';
87
- const PLUGIN_APPLY_BLOCK = "apply plugin: 'com.mikepenz.aboutlibraries.plugin'";
88
- const PLUGIN_APPLY_BLOCK_IDENTIFIER = 'com.mikepenz.aboutlibraries.plugin';
89
- const PLUGIN_CLASSPATH = 'com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin';
90
- const PLUGIN_VERSION = '11.6.3';
@@ -34,10 +34,20 @@ function addSettingsBundleUtil(iosProjectPath, addResourceFileToGroup) {
34
34
  * Creates a shell script build phase (if needed) and links it to native targets build phases
35
35
  */
36
36
  function registerLicensePlistBuildPhaseUtil(projectTargetId, pbxproj) {
37
+ const licensePlistFlags = '--add-version-numbers --output-path ./Settings.bundle';
38
+ const licensePlistShellScript = `set -e\\n\\nif [[ -n \${PODS_ROOT} ]]; then \${PODS_ROOT}/LicensePlist/license-plist ${licensePlistFlags}; else /usr/bin/env xcrun --sdk macosx swift run -c release --package-path ./build/generated/autolinking/libs/ReactNativeLegal/swift-tools license-plist ${licensePlistFlags}; fi\\n`;
37
39
  const nativeTargetSection = pbxproj.pbxNativeTargetSection();
38
40
  const nativeTarget = nativeTargetSection[projectTargetId];
39
- if (pbxproj.buildPhase(GENERATE_LICENSE_PLIST_BUILD_PHASE_COMMENT, projectTargetId)) {
40
- console.log(`LicensePlist buildPhase already added in "${nativeTarget.name}" - SKIP`);
41
+ const existingBuildPhase = pbxproj.buildPhaseObject('PBXShellScriptBuildPhase', GENERATE_LICENSE_PLIST_BUILD_PHASE_COMMENT, projectTargetId);
42
+ if (existingBuildPhase) {
43
+ const licensePlistShellScriptWithDoubleQuotes = '"' + licensePlistShellScript + '"';
44
+ if (existingBuildPhase.shellScript === licensePlistShellScriptWithDoubleQuotes) {
45
+ console.log(`LicensePlist buildPhase already added in "${nativeTarget.name}" - SKIP`);
46
+ }
47
+ else {
48
+ existingBuildPhase.shellScript = licensePlistShellScriptWithDoubleQuotes;
49
+ console.log(`LicensePlist buildPhase in "${nativeTarget.name}" - MODIFIED`);
50
+ }
41
51
  return pbxproj;
42
52
  }
43
53
  /**
@@ -47,7 +57,7 @@ function registerLicensePlistBuildPhaseUtil(projectTargetId, pbxproj) {
47
57
  */
48
58
  const newBuildPhase = pbxproj.addBuildPhase([], 'PBXShellScriptBuildPhase', GENERATE_LICENSE_PLIST_BUILD_PHASE_COMMENT, projectTargetId, {
49
59
  shellPath: '/bin/sh',
50
- shellScript: '${PODS_ROOT}/LicensePlist/license-plist --add-version-numbers --output-path ./Settings.bundle',
60
+ shellScript: licensePlistShellScript,
51
61
  });
52
62
  /**
53
63
  * In order to correctly link all metadata from `Settings.bundle` to the app
@@ -1,31 +1,64 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
1
4
  import { MiscUtils } from '@callstack/licenses';
2
5
 
6
+ const ANDROID_PLUGIN_APPLY_BLOCK_IDENTIFIER = 'com.mikepenz.aboutlibraries.plugin.android';
7
+ const ANDROID_PLUGIN_APPLY_BLOCK = `apply plugin: "${ANDROID_PLUGIN_APPLY_BLOCK_IDENTIFIER}"`;
8
+ const ANDROID_PLUGIN_CLASSPATH =
9
+ 'com.mikepenz.aboutlibraries.plugin.android:com.mikepenz.aboutlibraries.plugin.android.gradle.plugin';
10
+ const ANDROID_PLUGIN_DEFAULT_VERSION = '13.1.0';
11
+ const GRADLE_PLUGIN_PORTAL = 'gradlePluginPortal()';
12
+ const PLUGIN_APPLY_BLOCK_IDENTIFIER = 'com.mikepenz.aboutlibraries.plugin';
13
+
14
+ const OLD_PLUGIN_CLASSPATH = 'com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin';
15
+ const OLD_PLUGIN_CLASSPATH_REGEX = new RegExp(
16
+ `\\s+classpath\\(['"]${OLD_PLUGIN_CLASSPATH}:\\d+\\.\\d+\\.\\d+['"]\\)\\n`,
17
+ );
18
+ const DEPENDENCIES_BLOCK_DECLARATION_REGEX = new RegExp('dependencies\\s*{');
19
+ const REPOSITORIES_BLOCK_DECLARATION_REGEX = new RegExp('repositories\\s*{');
20
+ const APPLY_PLUGIN_BLOCK_REGEX = new RegExp(`apply\\s+plugin:\\s+['"]${PLUGIN_APPLY_BLOCK_IDENTIFIER}['"]\\n`);
21
+ const APPLY_ANDROID_PLUGIN_BLOCK_REGEX = new RegExp(
22
+ `apply\\s+plugin:\\s+['"]${ANDROID_PLUGIN_APPLY_BLOCK_IDENTIFIER}['"]`,
23
+ );
24
+ const OLD_PLUGIN_CONFIG_BLOCK_REGEX = new RegExp('(?:\\s*aboutLibraries\\s*{\\s+)(?:(?:\\S+\\s*=\\s*\\S+\\s+)*)(?:})');
25
+ const NEW_PLUGIN_CONFIG_GENERATED_START_COMMENT = '// GENERATED BY REACT-NATIVE-LEGAL DO NOT EDIT!\n';
26
+ const NEW_PLUGIN_CONFIG_GENERATED_END_COMMENT = '// END OF GENERATED BY REACT-NATIVE-LEGAL\n';
27
+ const NEW_PLUGIN_CONFIG_REGEX = new RegExp(
28
+ '(?:\\/\\/ GENERATED BY REACT-NATIVE-LEGAL DO NOT EDIT!\\n)(?:[\\s\\S]+)(?:\\/\\/ END OF GENERATED BY REACT-NATIVE-LEGAL\\n)',
29
+ );
30
+
3
31
  /**
4
32
  * Applies Gradle Plugin Portal & AboutLibraries Gradle plugin repositories (if needed) inside root build.gradle
5
33
  */
6
34
  export function declareAboutLibrariesPluginUtil(androidBuildGradleContent: string) {
7
- if (!androidBuildGradleContent.match(PLUGIN_CLASSPATH)?.length) {
8
- // Add Gradle Plugin Portal repository if it's not included
9
- if (!androidBuildGradleContent.match(GRADLE_PLUGIN_PORTAL_URL)?.length) {
10
- androidBuildGradleContent = androidBuildGradleContent.replace(
11
- /repositories\s?{/,
12
- `repositories {\n maven { url = uri("${GRADLE_PLUGIN_PORTAL_URL}") }`,
13
- );
14
- console.log('Gradle Plugin Portal repository - ADDED');
15
- } else {
16
- console.log('Gradle Plugin Portal repository already added - SKIP');
17
- }
35
+ if (androidBuildGradleContent.match(OLD_PLUGIN_CLASSPATH)?.length) {
36
+ // Remove old plugin
37
+ androidBuildGradleContent = androidBuildGradleContent.replace(OLD_PLUGIN_CLASSPATH_REGEX, '');
38
+ }
18
39
 
40
+ if (!androidBuildGradleContent.match(ANDROID_PLUGIN_CLASSPATH)?.length) {
19
41
  // Declare the AboutLibraries plugin
20
42
  androidBuildGradleContent = androidBuildGradleContent.replace(
21
- /dependencies\s?{/,
22
- `dependencies {\n classpath("${PLUGIN_CLASSPATH}:${PLUGIN_VERSION}")`,
43
+ DEPENDENCIES_BLOCK_DECLARATION_REGEX,
44
+ `dependencies {\n classpath("${ANDROID_PLUGIN_CLASSPATH}:${ANDROID_PLUGIN_DEFAULT_VERSION}")`,
23
45
  );
24
46
  console.log('About Libraries Gradle Plugin repository - ADDED');
25
47
  } else {
26
48
  console.log('About Libraries Gradle Plugin already added - SKIP');
27
49
  }
28
50
 
51
+ if (androidBuildGradleContent.match(GRADLE_PLUGIN_PORTAL_URL)?.length) {
52
+ console.log('Gradle Plugin Portal repository already added - SKIP');
53
+ } else if (!androidBuildGradleContent.match(GRADLE_PLUGIN_PORTAL)?.length) {
54
+ // Add Gradle Plugin Portal repository if it's not included
55
+ androidBuildGradleContent = androidBuildGradleContent.replace(
56
+ REPOSITORIES_BLOCK_DECLARATION_REGEX,
57
+ 'repositories {\n gradlePluginPortal()',
58
+ );
59
+ console.log('Gradle Plugin Portal repository - ADDED');
60
+ }
61
+
29
62
  return androidBuildGradleContent;
30
63
  }
31
64
 
@@ -33,26 +66,45 @@ export function declareAboutLibrariesPluginUtil(androidBuildGradleContent: strin
33
66
  * Applies and configures AboutLibraries Grale plugin (if needed) inside app's build.gradle
34
67
  */
35
68
  export function applyAndConfigureAboutLibrariesPluginUtil(androidAppBuildGradleContent: string) {
36
- // Apply plugin
37
- const applyPluginBlockRegex = new RegExp(`apply\\s+plugin:\\s+['"]${PLUGIN_APPLY_BLOCK_IDENTIFIER}['"]`);
69
+ if (androidAppBuildGradleContent.match(APPLY_PLUGIN_BLOCK_REGEX)?.length) {
70
+ // Remove old plugin
71
+ androidAppBuildGradleContent = androidAppBuildGradleContent.replace(APPLY_PLUGIN_BLOCK_REGEX, '');
72
+ }
73
+
74
+ // Remove old configuration
75
+ androidAppBuildGradleContent = androidAppBuildGradleContent.replace(OLD_PLUGIN_CONFIG_BLOCK_REGEX, '');
38
76
 
39
- if (!androidAppBuildGradleContent.match(applyPluginBlockRegex)?.length) {
40
- androidAppBuildGradleContent += `\n${PLUGIN_APPLY_BLOCK}`;
77
+ if (!androidAppBuildGradleContent.match(APPLY_ANDROID_PLUGIN_BLOCK_REGEX)?.length) {
78
+ // Apply plugin
79
+ androidAppBuildGradleContent += `\n${ANDROID_PLUGIN_APPLY_BLOCK}\n`;
41
80
  console.log('About Libraries Gradle Plugin - APPLIED');
42
81
  } else {
43
82
  console.log('About Libraries Gradle Plugin already applied - SKIP');
44
83
  }
45
84
 
46
- // Configure plugin
47
- const pluginConfigRegex = /aboutLibraries {/;
85
+ let aboutLibrariesConfig = '\n';
48
86
 
49
- if (!androidAppBuildGradleContent.match(pluginConfigRegex)?.length) {
50
- androidAppBuildGradleContent += '\n\naboutLibraries {\n configPath = "config"\n prettyPrint = true\n}\n';
51
- console.log('About Libraries Gradle Plugin - CONFIGURED');
87
+ aboutLibrariesConfig += NEW_PLUGIN_CONFIG_GENERATED_START_COMMENT;
88
+ aboutLibrariesConfig += 'aboutLibraries {\n';
89
+ aboutLibrariesConfig += ' offlineMode = false\n';
90
+ aboutLibrariesConfig += ' collect.configPath = file("../config")\n';
91
+ aboutLibrariesConfig += ' collect.fetchRemoteLicense = false\n';
92
+ aboutLibrariesConfig += ' collect.fetchRemoteFunding = false\n';
93
+ aboutLibrariesConfig += ' export {\n';
94
+ aboutLibrariesConfig += ' prettyPrint = true\n';
95
+ aboutLibrariesConfig += ' }\n';
96
+ aboutLibrariesConfig += '}\n';
97
+ aboutLibrariesConfig += NEW_PLUGIN_CONFIG_GENERATED_END_COMMENT;
98
+
99
+ // Configure plugin
100
+ if (androidAppBuildGradleContent.match(NEW_PLUGIN_CONFIG_REGEX)?.length) {
101
+ androidAppBuildGradleContent = androidAppBuildGradleContent.replace(NEW_PLUGIN_CONFIG_REGEX, aboutLibrariesConfig);
52
102
  } else {
53
- console.log('About Libraries Gradle Plugin already configured - SKIP');
103
+ androidAppBuildGradleContent += aboutLibrariesConfig;
54
104
  }
55
105
 
106
+ console.log('About Libraries Gradle Plugin - CONFIGURED');
107
+
56
108
  return androidAppBuildGradleContent;
57
109
  }
58
110
 
@@ -91,9 +143,29 @@ function prepareListActivity() {
91
143
  } as const;
92
144
  }
93
145
 
146
+ const RESOURCE_KEEP_FILE_CONTENT = `<?xml version="1.0" encoding="utf-8"?>
147
+ <resources xmlns:tools="http://schemas.android.com/tools"
148
+ tools:keep="@raw/aboutlibraries" />
149
+ `;
150
+
151
+ /**
152
+ * adds a file that will keep the About Libraries json resource when resource shrinking is enabled
153
+ */
154
+ export function addResourceKeepFileUtil(androidProjectRootDir: string) {
155
+ const rawResourcesDir = path.join(androidProjectRootDir, 'app/src/main/res/raw');
156
+ const keepFilePath = path.join(rawResourcesDir, 'com_reactnativelegal_keep.xml');
157
+
158
+ if (!fs.existsSync(rawResourcesDir)) {
159
+ fs.mkdirSync(rawResourcesDir, { recursive: true });
160
+ }
161
+
162
+ if (!fs.existsSync(keepFilePath)) {
163
+ fs.writeFileSync(keepFilePath, RESOURCE_KEEP_FILE_CONTENT);
164
+ console.log('Android resource keep file - ADDED');
165
+ } else {
166
+ console.log('Android resource keep file already exists - SKIPPED');
167
+ }
168
+ }
169
+
94
170
  const GRADLE_PLUGIN_PORTAL_URL = 'https://plugins.gradle.org/m2';
95
171
  const PLUGIN_ACTIVITY = 'com.reactnativelegal.ReactNativeLegalActivity';
96
- const PLUGIN_APPLY_BLOCK = "apply plugin: 'com.mikepenz.aboutlibraries.plugin'";
97
- const PLUGIN_APPLY_BLOCK_IDENTIFIER = 'com.mikepenz.aboutlibraries.plugin';
98
- const PLUGIN_CLASSPATH = 'com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin';
99
- const PLUGIN_VERSION = '11.6.3';
@@ -39,11 +39,27 @@ export function registerLicensePlistBuildPhaseUtil(
39
39
  projectTargetId: string,
40
40
  pbxproj: XcodeProject, // Xcode Pbxproj
41
41
  ) {
42
+ const licensePlistFlags = '--add-version-numbers --output-path ./Settings.bundle';
43
+ const licensePlistShellScript = `set -e\\n\\nif [[ -n \${PODS_ROOT} ]]; then \${PODS_ROOT}/LicensePlist/license-plist ${licensePlistFlags}; else /usr/bin/env xcrun --sdk macosx swift run -c release --package-path ./build/generated/autolinking/libs/ReactNativeLegal/swift-tools license-plist ${licensePlistFlags}; fi\\n`;
42
44
  const nativeTargetSection = pbxproj.pbxNativeTargetSection();
43
45
  const nativeTarget = nativeTargetSection[projectTargetId];
44
46
 
45
- if (pbxproj.buildPhase(GENERATE_LICENSE_PLIST_BUILD_PHASE_COMMENT, projectTargetId)) {
46
- console.log(`LicensePlist buildPhase already added in "${nativeTarget.name}" - SKIP`);
47
+ const existingBuildPhase = pbxproj.buildPhaseObject(
48
+ 'PBXShellScriptBuildPhase',
49
+ GENERATE_LICENSE_PLIST_BUILD_PHASE_COMMENT,
50
+ projectTargetId,
51
+ );
52
+
53
+ if (existingBuildPhase) {
54
+ const licensePlistShellScriptWithDoubleQuotes = '"' + licensePlistShellScript + '"';
55
+
56
+ if (existingBuildPhase.shellScript === licensePlistShellScriptWithDoubleQuotes) {
57
+ console.log(`LicensePlist buildPhase already added in "${nativeTarget.name}" - SKIP`);
58
+ } else {
59
+ existingBuildPhase.shellScript = licensePlistShellScriptWithDoubleQuotes;
60
+ console.log(`LicensePlist buildPhase in "${nativeTarget.name}" - MODIFIED`);
61
+ }
62
+
47
63
  return pbxproj;
48
64
  }
49
65
 
@@ -59,7 +75,7 @@ export function registerLicensePlistBuildPhaseUtil(
59
75
  projectTargetId,
60
76
  {
61
77
  shellPath: '/bin/sh',
62
- shellScript: '${PODS_ROOT}/LicensePlist/license-plist --add-version-numbers --output-path ./Settings.bundle',
78
+ shellScript: licensePlistShellScript,
63
79
  },
64
80
  );
65
81
  /**
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "declaration": true,
4
- "lib": ["es2020"],
5
- "module": "commonjs",
4
+ "lib": ["es2020", "DOM"],
5
+ "module": "node16",
6
6
  "target": "es2020",
7
7
 
8
8
  "strict": true,
9
9
  "esModuleInterop": true,
10
10
  "skipLibCheck": true,
11
11
  "forceConsistentCasingInFileNames": true,
12
- "moduleResolution": "node",
12
+ "moduleResolution": "node16",
13
13
 
14
14
  "outDir": "build",
15
15
  "rootDir": "src",
16
- "typeRoots": ["../types-definitions", "../../../node_modules/@types"]
16
+ "typeRoots": ["../types-definitions", "../../../node_modules/@types"],
17
+ "types": ["node", "xcode"]
17
18
  },
18
19
  "include": ["./src"],
19
20
  "exclude": ["**/__mocks__/*", "**/__tests__/*"]