react-native-legal 1.7.0 → 1.8.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 (28) hide show
  1. package/android/build.gradle +36 -29
  2. package/android/gradle.properties +7 -0
  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/package.json +2 -1
  19. package/plugin/build/android/addResourceKeepFile.d.ts +5 -0
  20. package/plugin/build/android/addResourceKeepFile.js +17 -0
  21. package/plugin/build/android/withAndroidLegal.js +2 -0
  22. package/plugin/src/android/addResourceKeepFile.ts +17 -0
  23. package/plugin/src/android/withAndroidLegal.ts +2 -0
  24. package/plugin-utils/build/android.d.ts +4 -0
  25. package/plugin-utils/build/android.js +82 -23
  26. package/plugin-utils/src/android.ts +99 -27
  27. package/android/src/main/res/values/colors.xml +0 -3
  28. package/android/src/main/res/values-night/colors.xml +0 -3
@@ -1,25 +1,18 @@
1
1
  buildscript {
2
- ext.safeExtGet = {prop, fallback ->
3
- rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
4
- }
5
-
6
- def kotlin_version = safeExtGet('kotlinVersion', '1.7.22')
2
+ def agp_version = rootProject.ext.has('androidGradlePluginVersion') ? rootProject.ext.get('androidGradlePluginVersion') : project.properties['ReactNativeLegal_androidGradlePluginVersion']
3
+ def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['ReactNativeLegal_kotlinVersion']
7
4
 
8
5
  repositories {
9
6
  google()
10
7
  gradlePluginPortal()
11
8
  }
12
9
  dependencies {
13
- classpath("com.android.tools.build:gradle:7.2.1")
14
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
15
- classpath("com.diffplug.spotless:com.diffplug.spotless.gradle.plugin:7.0.2")
10
+ classpath("com.android.tools.build:gradle:$agp_version")
11
+ classpath("org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin:$kotlin_version")
12
+ classpath("com.diffplug.spotless:com.diffplug.spotless.gradle.plugin:8.10.2")
16
13
  }
17
14
  }
18
15
 
19
- def isNewArchitectureEnabled() {
20
- return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
21
- }
22
-
23
16
  if (project == rootProject) {
24
17
  apply from: 'spotless.gradle'
25
18
  }
@@ -33,28 +26,37 @@ if (project.extensions.findByName('kotlin') == null) {
33
26
  apply plugin: 'kotlin-android'
34
27
  }
35
28
 
36
- if (isNewArchitectureEnabled()) {
29
+ if (project != rootProject) {
37
30
  apply plugin: "com.facebook.react"
38
31
  }
39
32
 
33
+ apply plugin: "org.jetbrains.kotlin.plugin.compose"
34
+
35
+ def getOrExtDefault(name) {
36
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeLegal_' + name]
37
+ }
38
+
39
+ def getOrExtIntegerDefault(name) {
40
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['ReactNativeLegal_' + name]).toInteger()
41
+ }
42
+
40
43
  android {
41
- compileSdkVersion safeExtGet('compileSdkVersion', 33)
44
+ compileSdkVersion getOrExtIntegerDefault('compileSdkVersion')
42
45
 
43
46
  namespace "com.reactnativelegal"
44
47
 
45
48
  defaultConfig {
46
- minSdkVersion safeExtGet('minSdkVersion', 21)
47
- targetSdkVersion safeExtGet('targetSdkVersion', 33)
48
- buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
49
+ minSdkVersion getOrExtIntegerDefault('minSdkVersion')
50
+ targetSdkVersion getOrExtIntegerDefault('targetSdkVersion')
51
+ }
52
+
53
+ buildFeatures {
54
+ compose true
49
55
  }
50
56
 
51
57
  sourceSets {
52
58
  main {
53
- if (isNewArchitectureEnabled()) {
54
- java.srcDirs += ['src/newarch/java', "${project.buildDir}/generated/source/codegen/java"]
55
- } else {
56
- java.srcDirs += ['src/oldarch/java']
57
- }
59
+ java.srcDirs += ['src/newarch/java', "${project.buildDir}/generated/source/codegen/java"]
58
60
  }
59
61
  }
60
62
  }
@@ -70,12 +72,17 @@ repositories {
70
72
  dependencies {
71
73
  implementation "com.facebook.react:react-android" // Set by the React Native Gradle Plugin
72
74
 
73
- def aboutLibrariesPluginVersion = "10.8.3"
74
- implementation("com.mikepenz:aboutlibraries-core-android:$aboutLibrariesPluginVersion")
75
- implementation("com.mikepenz:aboutlibraries:$aboutLibrariesPluginVersion") {
76
- exclude group: 'com.mikepenz', module: 'aboutlibraries-core'
77
- }
75
+ def aboutLibrariesVersion = getOrExtDefault('aboutLibrariesVersion')
76
+ implementation("com.mikepenz:aboutlibraries-core:$aboutLibrariesVersion")
77
+ implementation("com.mikepenz:aboutlibraries-compose-m3:$aboutLibrariesVersion")
78
78
 
79
- def constraintLayoutVersion = "2.1.4"
80
- implementation("androidx.constraintlayout:constraintlayout:$constraintLayoutVersion")
79
+ def composeBomVersion = getOrExtDefault('composeBomVersion')
80
+ Dependency composeBom = platform("androidx.compose:compose-bom:$composeBomVersion")
81
+ implementation composeBom
82
+ implementation("androidx.compose.foundation:foundation")
83
+ implementation("androidx.compose.material:material")
84
+ implementation("androidx.compose.material:material-icons-core")
85
+ implementation("androidx.compose.material3:material3")
86
+ implementation("androidx.compose.runtime:runtime")
87
+ implementation("androidx.compose.ui:ui")
81
88
  }
@@ -0,0 +1,7 @@
1
+ ReactNativeLegal_androidGradlePluginVersion=8.12.0
2
+ ReactNativeLegal_composeBomVersion=2025.11.01
3
+ ReactNativeLegal_kotlinVersion=2.1.20
4
+ ReactNativeLegal_compileSdkVersion=36
5
+ ReactNativeLegal_minSdkVersion=21
6
+ ReactNativeLegal_targetSdkVersion=35
7
+ ReactNativeLegal_aboutLibrariesVersion=13.1.0
@@ -5,25 +5,39 @@ import android.content.res.Configuration
5
5
  import android.graphics.Color
6
6
  import android.os.Build
7
7
  import android.os.Bundle
8
- import android.view.MenuItem
9
- import android.view.View
10
8
  import android.view.WindowManager
11
9
  import androidx.appcompat.app.AppCompatActivity
12
- import androidx.appcompat.widget.Toolbar
10
+ import androidx.compose.foundation.isSystemInDarkTheme
11
+ import androidx.compose.foundation.layout.Arrangement
12
+ import androidx.compose.foundation.layout.Column
13
+ import androidx.compose.foundation.layout.fillMaxSize
14
+ import androidx.compose.foundation.layout.padding
15
+ import androidx.compose.material.icons.Icons
16
+ import androidx.compose.material.icons.automirrored.filled.ArrowBack
17
+ import androidx.compose.material3.CenterAlignedTopAppBar
18
+ import androidx.compose.material3.ExperimentalMaterial3Api
19
+ import androidx.compose.material3.Icon
20
+ import androidx.compose.material3.IconButton
21
+ import androidx.compose.material3.MaterialTheme
22
+ import androidx.compose.material3.Scaffold
23
+ import androidx.compose.material3.Text
24
+ import androidx.compose.material3.TopAppBarDefaults
25
+ import androidx.compose.material3.darkColorScheme
26
+ import androidx.compose.material3.lightColorScheme
27
+ import androidx.compose.material3.rememberTopAppBarState
28
+ import androidx.compose.runtime.getValue
29
+ import androidx.compose.ui.Alignment
30
+ import androidx.compose.ui.Modifier
31
+ import androidx.compose.ui.input.nestedscroll.nestedScroll
32
+ import androidx.compose.ui.platform.ComposeView
33
+ import androidx.compose.ui.text.style.TextOverflow
13
34
  import androidx.core.view.WindowCompat
14
- import androidx.core.view.WindowInsetsCompat
15
35
  import androidx.core.view.WindowInsetsControllerCompat
16
- import androidx.core.view.updatePadding
17
- import com.mikepenz.aboutlibraries.LibsBuilder.Companion.BUNDLE_TITLE
18
- import com.mikepenz.aboutlibraries.ui.LibsSupportFragment
36
+ import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries
37
+ import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
19
38
 
20
- /**
21
- * Based on AboutLibraries LibsActivity, but simplified (no search filter), with improved back
22
- * handling and hidden Toolbar/ActionBar for TV devices
23
- */
39
+ @OptIn(ExperimentalMaterial3Api::class)
24
40
  class ReactNativeLegalActivity : AppCompatActivity() {
25
- private lateinit var fragment: LibsSupportFragment
26
-
27
41
  override fun onCreate(savedInstanceState: Bundle?) {
28
42
  setTheme(R.style.ReactNativeLegalTheme)
29
43
  super.onCreate(savedInstanceState)
@@ -32,75 +46,58 @@ class ReactNativeLegalActivity : AppCompatActivity() {
32
46
  setupEdgeToEdge()
33
47
 
34
48
  val bundle = intent.extras
35
- fragment = LibsSupportFragment().apply { arguments = bundle }
49
+ val id = bundle?.getInt("id") ?: -1
50
+ val title = bundle?.getString("title", "") ?: ""
51
+ val composeView = findViewById<ComposeView>(R.id.compose_view)
36
52
 
37
53
  // https://developer.android.com/training/tv/start/hardware.html#runtime-check
38
54
  val isTVDevice = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
39
55
 
40
- if (isTVDevice) {
41
- hideToolbar()
42
- } else {
43
- setupToolbar(bundle)
44
- }
45
-
46
- supportFragmentManager
47
- .beginTransaction()
48
- .replace(R.id.fragment_container, fragment)
49
- .commit()
50
- }
51
-
52
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
53
- if (item.itemId == android.R.id.home) {
54
- onBackPressedDispatcher.onBackPressed()
55
- return true
56
- }
57
- return super.onOptionsItemSelected(item)
58
- }
59
-
60
- private fun hideToolbar() {
61
- val toolbar = findViewById<Toolbar>(R.id.toolbar)
62
- toolbar.visibility = View.GONE
63
- supportActionBar?.hide()
64
- }
65
-
66
- private fun setupToolbar(bundle: Bundle?) {
67
- val title = bundle?.getString(BUNDLE_TITLE, "") ?: ""
68
-
69
- val toolbar = findViewById<Toolbar>(R.id.toolbar)
70
- setSupportActionBar(toolbar)
71
-
72
- supportActionBar?.let {
73
- it.setDisplayHomeAsUpEnabled(true)
74
- it.setDisplayShowTitleEnabled(title.isNotEmpty())
75
- it.title = title
76
- }
77
-
78
- toolbar.setOnApplyWindowInsetsListener { v, insets ->
79
- val systemInsets =
80
- WindowInsetsCompat.toWindowInsetsCompat(insets)
81
- .getInsets(WindowInsetsCompat.Type.systemBars())
82
- v.updatePadding(
83
- left = systemInsets.left,
84
- top = systemInsets.top,
85
- right = systemInsets.right,
86
- )
87
-
88
- insets
89
- }
90
-
91
- if (toolbar.isAttachedToWindow) {
92
- toolbar.requestApplyInsets()
93
- } else {
94
- toolbar.addOnAttachStateChangeListener(
95
- object : View.OnAttachStateChangeListener {
96
- override fun onViewAttachedToWindow(v: View) {
97
- v.removeOnAttachStateChangeListener(this)
98
- v.requestApplyInsets()
56
+ composeView.setContent {
57
+ val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
58
+
59
+ MaterialTheme(
60
+ colorScheme = if (isSystemInDarkTheme()) darkColorScheme() else lightColorScheme()
61
+ ) {
62
+ Scaffold(
63
+ modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
64
+ topBar = {
65
+ if (!isTVDevice) {
66
+ CenterAlignedTopAppBar(
67
+ title = {
68
+ Text(title, maxLines = 1, overflow = TextOverflow.Ellipsis)
69
+ },
70
+ navigationIcon = {
71
+ IconButton(
72
+ onClick = { onBackPressedDispatcher.onBackPressed() }
73
+ ) {
74
+ Icon(
75
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack,
76
+ contentDescription = "Go back",
77
+ )
78
+ }
79
+ },
80
+ )
81
+ }
82
+ },
83
+ ) { innerPadding ->
84
+ if (id == -1) {
85
+ Column(
86
+ modifier = Modifier.fillMaxSize().padding(innerPadding),
87
+ horizontalAlignment = Alignment.CenterHorizontally,
88
+ verticalArrangement = Arrangement.Center,
89
+ ) {
90
+ Text("Incorrect resource identifier provided")
91
+ }
92
+ } else {
93
+ val libraries by produceLibraries(id)
94
+ LibrariesContainer(
95
+ libraries = libraries,
96
+ modifier = Modifier.fillMaxSize().padding(innerPadding),
97
+ )
99
98
  }
100
-
101
- override fun onViewDetachedFromWindow(v: View) = Unit
102
99
  }
103
- )
100
+ }
104
101
  }
105
102
  }
106
103
 
@@ -1,5 +1,6 @@
1
1
  package com.reactnativelegal
2
2
 
3
+ import android.content.Context
3
4
  import android.content.Intent
4
5
  import android.os.Bundle
5
6
  import androidx.core.os.bundleOf
@@ -7,20 +8,20 @@ import com.facebook.react.bridge.Arguments
7
8
  import com.facebook.react.bridge.ReactApplicationContext
8
9
  import com.facebook.react.bridge.WritableMap
9
10
  import com.mikepenz.aboutlibraries.Libs
10
- import com.mikepenz.aboutlibraries.LibsBuilder
11
- import com.mikepenz.aboutlibraries.util.withContext
12
11
 
13
12
  object ReactNativeLegalModuleImpl {
14
13
  const val NAME = "ReactNativeLegalModule"
15
14
 
16
15
  private var cachedData: List<Bundle>? = null
16
+ private var cachedId: Int = -1
17
17
 
18
18
  fun launchLicenseListScreen(reactContext: ReactApplicationContext, licenseHeaderText: String) {
19
19
  val context = reactContext.currentActivity ?: return
20
+ val id = getOrInitLibrariesResourceIdentifier(context)
20
21
  val intent =
21
22
  Intent(context, ReactNativeLegalActivity::class.java).apply {
22
- this.putExtra("data", LibsBuilder())
23
- this.putExtra(LibsBuilder.BUNDLE_TITLE, licenseHeaderText)
23
+ this.putExtra("id", id)
24
+ this.putExtra("title", licenseHeaderText)
24
25
  }
25
26
 
26
27
  context.startActivity(intent)
@@ -31,14 +32,31 @@ object ReactNativeLegalModuleImpl {
31
32
  cachedData = retrieveLibrariesArray(reactContext)
32
33
  }
33
34
 
34
- val libraries = cachedData ?: emptyList<Bundle>()
35
+ val libraries = cachedData ?: emptyList()
35
36
  return Arguments.createMap().apply { putArray("data", Arguments.fromList(libraries)) }
36
37
  }
37
38
 
39
+ private fun getOrInitLibrariesResourceIdentifier(context: Context): Int {
40
+ if (cachedId == -1) {
41
+ cachedId =
42
+ context.resources.getIdentifier(
43
+ "aboutlibraries",
44
+ "raw",
45
+ context.packageName,
46
+ )
47
+ }
48
+ return cachedId
49
+ }
50
+
38
51
  private fun retrieveLibrariesArray(reactContext: ReactApplicationContext): List<Bundle>? {
39
52
  val context = reactContext.currentActivity ?: return null
40
53
 
41
- val libraries = Libs.Builder().withContext(context).build().libraries
54
+ val jsonString =
55
+ context.resources
56
+ .openRawResource(getOrInitLibrariesResourceIdentifier(context))
57
+ .bufferedReader()
58
+ .use { it.readText() }
59
+ val libraries = Libs.Builder().withJson(jsonString).build().libraries
42
60
 
43
61
  return libraries.map { library ->
44
62
  bundleOf(
@@ -1,28 +1,6 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
- <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
- xmlns:app="http://schemas.android.com/apk/res-auto"
2
+ <androidx.compose.ui.platform.ComposeView
3
+ xmlns:android="http://schemas.android.com/apk/res/android"
4
+ android:id="@+id/compose_view"
4
5
  android:layout_width="match_parent"
5
- android:layout_height="match_parent">
6
-
7
- <androidx.appcompat.widget.Toolbar
8
- android:id="@+id/toolbar"
9
- style="?toolbarStyle"
10
- android:layout_width="0dp"
11
- android:layout_height="wrap_content"
12
- app:contentInsetStart="0dp"
13
- app:contentInsetStartWithNavigation="0dp"
14
- app:elevation="4dp"
15
- app:layout_constraintEnd_toEndOf="parent"
16
- app:layout_constraintStart_toStartOf="parent"
17
- app:layout_constraintTop_toTopOf="parent" />
18
-
19
- <androidx.fragment.app.FragmentContainerView
20
- android:id="@+id/fragment_container"
21
- android:layout_width="0dp"
22
- android:layout_height="0dp"
23
- app:layout_constraintBottom_toBottomOf="parent"
24
- app:layout_constraintEnd_toEndOf="parent"
25
- app:layout_constraintStart_toStartOf="parent"
26
- app:layout_constraintTop_toBottomOf="@id/toolbar" />
27
-
28
- </androidx.constraintlayout.widget.ConstraintLayout>
6
+ android:layout_height="match_parent" />
@@ -1,7 +1,5 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <resources>
3
- <style name="ReactNativeLegalTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
4
- <item name="android:statusBarColor">?attr/colorSurface</item>
5
- <item name="android:windowBackground">?attr/colorSurface</item>
3
+ <style name="ReactNativeLegalTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
6
4
  </style>
7
5
  </resources>
@@ -4,14 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.addListActivity = addListActivity;
7
- const path_1 = __importDefault(require("path"));
7
+ const node_path_1 = __importDefault(require("node:path"));
8
8
  const android_1 = require("../../../plugin-utils/build/android");
9
9
  const utils_1 = require("./utils");
10
10
  /**
11
11
  * Adds an Android Activity with list of dependencies and their licenses to project's AndroidManifest.xml
12
12
  */
13
13
  async function addListActivity(androidProjectPath) {
14
- const androidManifestPath = path_1.default.join(androidProjectPath, 'app', 'src', 'main', 'AndroidManifest.xml');
14
+ const androidManifestPath = node_path_1.default.join(androidProjectPath, 'app', 'src', 'main', 'AndroidManifest.xml');
15
15
  await (0, utils_1.modifyXMLFileContent)(androidManifestPath, (manifestObj) => {
16
16
  if (manifestObj.manifest.application?.[0]?.activity) {
17
17
  manifestObj.manifest.application[0].activity = (0, android_1.addListActivityUtil)(manifestObj.manifest.application?.[0].activity);
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Adds a file that will keep the About Libraries json resource when resource shrinking is enabled
3
+ */
4
+ export declare function addResourceKeepFile(androidProjectPath: string): void;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addResourceKeepFile = addResourceKeepFile;
4
+ const android_1 = require("../../../plugin-utils/build/android");
5
+ /**
6
+ * Adds a file that will keep the About Libraries json resource when resource shrinking is enabled
7
+ */
8
+ function addResourceKeepFile(androidProjectPath) {
9
+ (0, android_1.addResourceKeepFileUtil)(androidProjectPath);
10
+ }
@@ -8,6 +8,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const licenses_1 = require("@callstack/licenses");
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,4 +26,5 @@ function androidCommand(androidProjectPath, scanOptionsFactory) {
25
26
  (0, declareAboutLibrariesPlugin_1.declareAboutLibrariesPlugin)(androidProjectPath);
26
27
  (0, applyAndConfigureAboutLibrariesPlugin_1.applyAndConfigureAboutLibrariesPlugin)(androidProjectPath);
27
28
  (0, addListActivity_1.addListActivity)(androidProjectPath);
29
+ (0, addResourceKeepFile_1.addResourceKeepFile)(androidProjectPath);
28
30
  }
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.applyAndConfigureAboutLibrariesPlugin = applyAndConfigureAboutLibrariesPlugin;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
9
  const android_1 = require("../../../plugin-utils/build/android");
10
10
  const utils_1 = require("./utils");
11
11
  /**
@@ -14,11 +14,11 @@ const utils_1 = require("./utils");
14
14
  * NOTE: As of now, it doesn't support build.gradle.kts (Gradle Kotlin Script)
15
15
  */
16
16
  function applyAndConfigureAboutLibrariesPlugin(androidProjectPath) {
17
- if (fs_1.default.existsSync(path_1.default.join(androidProjectPath, 'app', 'build.gradle.kts'))) {
17
+ if (node_fs_1.default.existsSync(node_path_1.default.join(androidProjectPath, 'app', 'build.gradle.kts'))) {
18
18
  console.warn('Gradle Kotlin scripts are not supported yet');
19
19
  }
20
- else if (fs_1.default.existsSync(path_1.default.join(androidProjectPath, 'app', 'build.gradle'))) {
21
- (0, utils_1.modifyFileContent)(path_1.default.join(androidProjectPath, 'app', 'build.gradle'), android_1.applyAndConfigureAboutLibrariesPluginUtil);
20
+ else if (node_fs_1.default.existsSync(node_path_1.default.join(androidProjectPath, 'app', 'build.gradle'))) {
21
+ (0, utils_1.modifyFileContent)(node_path_1.default.join(androidProjectPath, 'app', 'build.gradle'), android_1.applyAndConfigureAboutLibrariesPluginUtil);
22
22
  }
23
23
  else {
24
24
  console.warn('Cannot find app/build.gradle file');
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.declareAboutLibrariesPlugin = declareAboutLibrariesPlugin;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
9
  const android_1 = require("../../../plugin-utils/build/android");
10
10
  const utils_1 = require("./utils");
11
11
  /**
@@ -14,11 +14,11 @@ const utils_1 = require("./utils");
14
14
  * NOTE: As of now, it doesn't support build.gradle.kts (Gradle Kotlin Script)
15
15
  */
16
16
  function declareAboutLibrariesPlugin(androidProjectPath) {
17
- if (fs_1.default.existsSync(path_1.default.join(androidProjectPath, 'build.gradle.kts'))) {
17
+ if (node_fs_1.default.existsSync(node_path_1.default.join(androidProjectPath, 'build.gradle.kts'))) {
18
18
  console.warn('Gradle Kotlin scripts are not supported yet');
19
19
  }
20
- else if (fs_1.default.existsSync(path_1.default.join(androidProjectPath, 'build.gradle'))) {
21
- (0, utils_1.modifyFileContent)(path_1.default.join(androidProjectPath, 'build.gradle'), android_1.declareAboutLibrariesPluginUtil);
20
+ else if (node_fs_1.default.existsSync(node_path_1.default.join(androidProjectPath, 'build.gradle'))) {
21
+ (0, utils_1.modifyFileContent)(node_path_1.default.join(androidProjectPath, 'build.gradle'), android_1.declareAboutLibrariesPluginUtil);
22
22
  }
23
23
  else {
24
24
  console.warn('Cannot find build.gradle file');
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
2
 
3
3
  import { addListActivityUtil } from '../../../plugin-utils/build/android';
4
4
 
@@ -0,0 +1,8 @@
1
+ import { addResourceKeepFileUtil } from '../../../plugin-utils/build/android';
2
+
3
+ /**
4
+ * Adds a file that will keep the About Libraries json resource when resource shrinking is enabled
5
+ */
6
+ export function addResourceKeepFile(androidProjectPath: string) {
7
+ addResourceKeepFileUtil(androidProjectPath);
8
+ }
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import { type Types as SharedTypes, scanDependencies, writeAboutLibrariesNPMOutput } from '@callstack/licenses';
5
5
 
6
6
  import { addListActivity } from './addListActivity';
7
+ import { addResourceKeepFile } from './addResourceKeepFile';
7
8
  import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin';
8
9
  import { declareAboutLibrariesPlugin } from './declareAboutLibrariesPlugin';
9
10
 
@@ -29,4 +30,5 @@ export function androidCommand(androidProjectPath: string, scanOptionsFactory: S
29
30
  declareAboutLibrariesPlugin(androidProjectPath);
30
31
  applyAndConfigureAboutLibrariesPlugin(androidProjectPath);
31
32
  addListActivity(androidProjectPath);
33
+ addResourceKeepFile(androidProjectPath);
32
34
  }
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
 
4
4
  import { applyAndConfigureAboutLibrariesPluginUtil } from '../../../plugin-utils/build/android';
5
5
 
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
 
4
4
  import { declareAboutLibrariesPluginUtil } from '../../../plugin-utils/build/android';
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-legal",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Acknowledge OSS libraries used in your React Native app",
5
5
  "keywords": [
6
6
  "react-native",
@@ -31,6 +31,7 @@
31
31
  "files": [
32
32
  "android/src",
33
33
  "android/build.gradle",
34
+ "android/gradle.properties",
34
35
  "bare-plugin",
35
36
  "ios",
36
37
  "lib",
@@ -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';
@@ -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';
@@ -1,3 +0,0 @@
1
- <resources>
2
- <color name="surface">#F3EFEE</color>
3
- </resources>
@@ -1,3 +0,0 @@
1
- <resources>
2
- <color name="surface">#121212</color>
3
- </resources>