@granite-js/screen 1.0.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.
- package/CHANGELOG.md +7 -0
- package/GraniteScreen.podspec +25 -0
- package/LICENSE +202 -0
- package/android/CMakeLists.txt +62 -0
- package/android/build.gradle +63 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/BundleEvaluator.cpp +27 -0
- package/android/src/main/cpp/BundleEvaluator.h +17 -0
- package/android/src/main/cpp/onLoad.cpp +6 -0
- package/android/src/main/kotlin/run/granite/BundleEvaluator.kt +50 -0
- package/android/src/main/kotlin/run/granite/BundleLoader.kt +40 -0
- package/android/src/main/kotlin/run/granite/DefaultBundleLoader.kt +20 -0
- package/android/src/main/kotlin/run/granite/DefaultErrorView.kt +58 -0
- package/android/src/main/kotlin/run/granite/DefaultLoadingView.kt +51 -0
- package/android/src/main/kotlin/run/granite/GraniteReactDelegate.kt +76 -0
- package/android/src/main/kotlin/run/granite/GraniteReactDelegateImpl.kt +448 -0
- package/android/src/main/kotlin/run/granite/GraniteReactHost.kt +113 -0
- package/android/src/main/kotlin/run/granite/ReactHostFactory.kt +106 -0
- package/gradle-plugin/LICENSE +201 -0
- package/gradle-plugin/README.md +578 -0
- package/gradle-plugin/build.gradle.kts +97 -0
- package/gradle-plugin/gradle/libs.versions.toml +17 -0
- package/gradle-plugin/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle-plugin/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/gradle-plugin/gradle.properties +12 -0
- package/gradle-plugin/gradlew +248 -0
- package/gradle-plugin/gradlew.bat +93 -0
- package/gradle-plugin/settings.gradle.kts +1 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteExtension.kt +225 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GranitePlugin.kt +784 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteRootExtension.kt +107 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteRootProjectPlugin.kt +290 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/BuildConfigConfigurator.kt +69 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DependencyConfigurator.kt +232 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DependencyCoordinates.kt +29 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DevServerResourceConfigurator.kt +101 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/JniPackagingConfigurator.kt +160 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/NdkConfigurator.kt +135 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/RepositoryConfigurator.kt +148 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/ResourceConfigurator.kt +56 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/CMakeGenerator.kt +105 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/CppAutolinkingGenerator.kt +152 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/EntryPointGenerator.kt +100 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/AndroidDependencyConfig.kt +23 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/AutolinkingConfig.kt +89 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/CMakeEntry.kt +47 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/NativeModule.kt +177 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/AssetPackagingTask.kt +194 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/AutolinkingTask.kt +431 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/BundleTask.kt +275 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/CodegenArtifactsTask.kt +218 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/CodegenSchemaTask.kt +186 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/AutolinkingParser.kt +128 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/ConflictDetector.kt +121 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/JdkValidator.kt +73 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/NodeExecutableFinder.kt +43 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/ReactNativeVersionReader.kt +329 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/TaskDependencyValidator.kt +198 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GraniteExtensionTest.kt +191 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GranitePluginTest.kt +156 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GraniteRootProjectPluginTest.kt +87 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/BuildConfigConfiguratorTest.kt +115 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/DependencyConfiguratorTest.kt +338 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/DevServerResourceConfiguratorTest.kt +205 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/ResourceConfiguratorTest.kt +131 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/fixtures/NativeModuleFixtures.kt +67 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/CMakeGeneratorTest.kt +71 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/CppAutolinkingGeneratorTest.kt +344 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/EntryPointGeneratorTest.kt +40 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/AutolinkingConfigTest.kt +350 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/CMakeEntryTest.kt +200 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/NativeModuleTest.kt +562 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/AssetPackagingTaskTest.kt +318 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/AutolinkingTaskTest.kt +89 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/BundleTaskTest.kt +68 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/CodegenTasksTest.kt +410 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/AutolinkingParserTest.kt +335 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/ConflictDetectorTest.kt +75 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/JdkValidatorTest.kt +88 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/ReactNativeVersionReaderTest.kt +585 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/TaskDependencyValidatorTest.kt +123 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/TaskTestUtils.kt +88 -0
- package/gradle-plugin/src/test/resources/fixtures/sample-rn-config.json +45 -0
- package/ios/BundleLoader/BundleEvaluator.h +16 -0
- package/ios/BundleLoader/BundleEvaluator.mm +76 -0
- package/ios/BundleLoader/BundleLoadable.swift +91 -0
- package/ios/GraniteBundleLoaderTypes.swift +7 -0
- package/ios/GraniteScreen.h +12 -0
- package/ios/ReactNativeHosting/DefaultViews.swift +138 -0
- package/ios/ReactNativeHosting/GraniteDefaultModuleProvider.h +24 -0
- package/ios/ReactNativeHosting/GraniteDefaultModuleProvider.mm +22 -0
- package/ios/ReactNativeHosting/GraniteHostingHelper.swift +103 -0
- package/ios/ReactNativeHosting/GraniteNativeFactory.swift +35 -0
- package/ios/ReactNativeHosting/GraniteNativeFactoryDelegateImpl.swift +30 -0
- package/ios/ReactNativeHosting/GraniteNativeFactoryImpl.swift +24 -0
- package/ios/ReactNativeHosting/GraniteReactHost.swift +39 -0
- package/ios/ReactNativeHosting/GraniteScreen-Bridging-Header.h +12 -0
- package/package.json +59 -0
- package/react-native.config.js +8 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
package run.granite.gradle.models
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Enriched model representing a React Native native module with computed properties.
|
|
5
|
+
* This is the primary model used by code generators.
|
|
6
|
+
*
|
|
7
|
+
* Constructed from AndroidDependencyConfig with validation:
|
|
8
|
+
* - packageImportPath and packageInstance must both be present or both be null
|
|
9
|
+
*/
|
|
10
|
+
data class NativeModule(
|
|
11
|
+
val name: String,
|
|
12
|
+
val packageImportPath: String?,
|
|
13
|
+
val packageInstance: String?,
|
|
14
|
+
val dependencyConfiguration: String?,
|
|
15
|
+
val buildTypes: List<String>,
|
|
16
|
+
val libraryName: String?,
|
|
17
|
+
val componentDescriptors: List<String>,
|
|
18
|
+
val cmakeListsPath: String?,
|
|
19
|
+
val cxxModuleCMakeListsPath: String?,
|
|
20
|
+
val cxxModuleCMakeListsModuleName: String?,
|
|
21
|
+
val cxxModuleHeaderName: String?,
|
|
22
|
+
val isPureCxxDependency: Boolean,
|
|
23
|
+
/**
|
|
24
|
+
* True if the module's package.json has codegenConfig.includesGeneratedCode: true.
|
|
25
|
+
* Modules with this flag use their own codegen system (e.g., brick-codegen)
|
|
26
|
+
* and should be excluded from react-native-codegen based autolinking.
|
|
27
|
+
*/
|
|
28
|
+
val includesGeneratedCode: Boolean = false,
|
|
29
|
+
) {
|
|
30
|
+
init {
|
|
31
|
+
// Validate packageImportPath and packageInstance pairing
|
|
32
|
+
val hasImportPath = packageImportPath != null
|
|
33
|
+
val hasInstance = packageInstance != null
|
|
34
|
+
require(hasImportPath == hasInstance) {
|
|
35
|
+
"Module '$name': Failed to validate config - packageImportPath and packageInstance " +
|
|
36
|
+
"must both be present or both be null. Check module's react-native.config.js."
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* True if module has Java TurboModule implementation.
|
|
42
|
+
* Identified by non-null packageImportPath and packageInstance.
|
|
43
|
+
*/
|
|
44
|
+
val hasJavaImplementation: Boolean
|
|
45
|
+
get() = packageImportPath != null && packageInstance != null
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* True if module has C++ TurboModule implementation.
|
|
49
|
+
* Identified by non-null cxxModuleHeaderName.
|
|
50
|
+
*/
|
|
51
|
+
val hasCxxImplementation: Boolean
|
|
52
|
+
get() = cxxModuleHeaderName != null
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* True if module has any Fabric components.
|
|
56
|
+
* Identified by non-empty componentDescriptors array.
|
|
57
|
+
*/
|
|
58
|
+
val hasFabricComponents: Boolean
|
|
59
|
+
get() = componentDescriptors.isNotEmpty()
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* True if module has CMake configuration.
|
|
63
|
+
* Identified by non-null cmakeListsPath or cxxModuleCMakeListsPath.
|
|
64
|
+
*/
|
|
65
|
+
val hasCMakeConfiguration: Boolean
|
|
66
|
+
get() = cmakeListsPath != null || cxxModuleCMakeListsPath != null
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* True if module needs to be included in C++ autolinking.
|
|
70
|
+
* Required for C++ TurboModules or Fabric components.
|
|
71
|
+
*/
|
|
72
|
+
val needsCppAutolinking: Boolean
|
|
73
|
+
get() = hasCxxImplementation || hasFabricComponents
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns C++ identifier-safe name by sanitizing module name.
|
|
77
|
+
* Replaces invalid characters (spaces, hyphens, special chars) with underscores.
|
|
78
|
+
*/
|
|
79
|
+
fun sanitizedName(): String = name.replace(Regex("[^a-zA-Z0-9_]"), "_")
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns list of CMake entries for this module.
|
|
83
|
+
* Handles both standard CMakeLists.txt and separate cxxModule CMakeLists.txt.
|
|
84
|
+
*/
|
|
85
|
+
fun cmakeEntries(): List<CMakeEntry> {
|
|
86
|
+
val entries = mutableListOf<CMakeEntry>()
|
|
87
|
+
|
|
88
|
+
// Add standard CMakeLists.txt entry
|
|
89
|
+
cmakeListsPath?.let { path ->
|
|
90
|
+
entries.add(
|
|
91
|
+
CMakeEntry(
|
|
92
|
+
sourcePath = path,
|
|
93
|
+
buildDirName = "${libraryName}_autolinked_build",
|
|
94
|
+
libraryTargets = listOfNotNull(
|
|
95
|
+
libraryName?.let { "react_codegen_$it" },
|
|
96
|
+
),
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Add C++ TurboModule CMakeLists.txt entry
|
|
102
|
+
cxxModuleCMakeListsPath?.let { path ->
|
|
103
|
+
entries.add(
|
|
104
|
+
CMakeEntry(
|
|
105
|
+
sourcePath = path,
|
|
106
|
+
buildDirName = "${libraryName}_cxx_autolinked_build",
|
|
107
|
+
libraryTargets = listOfNotNull(cxxModuleCMakeListsModuleName),
|
|
108
|
+
),
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return entries
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
companion object {
|
|
116
|
+
/**
|
|
117
|
+
* Constructs NativeModule from AndroidDependencyConfig with validation.
|
|
118
|
+
* Treats null and missing optional fields identically.
|
|
119
|
+
*
|
|
120
|
+
* @param name Module name
|
|
121
|
+
* @param config Android dependency configuration
|
|
122
|
+
* @param moduleRootPath Root path of the module (for reading package.json)
|
|
123
|
+
*/
|
|
124
|
+
fun from(
|
|
125
|
+
name: String,
|
|
126
|
+
config: AndroidDependencyConfig,
|
|
127
|
+
moduleRootPath: String? = null,
|
|
128
|
+
): NativeModule {
|
|
129
|
+
val includesGeneratedCode = moduleRootPath?.let {
|
|
130
|
+
readIncludesGeneratedCodeFlag(it)
|
|
131
|
+
} ?: false
|
|
132
|
+
|
|
133
|
+
return NativeModule(
|
|
134
|
+
name = name,
|
|
135
|
+
packageImportPath = config.packageImportPath,
|
|
136
|
+
packageInstance = config.packageInstance,
|
|
137
|
+
dependencyConfiguration = config.dependencyConfiguration,
|
|
138
|
+
buildTypes = config.buildTypes.orEmpty(),
|
|
139
|
+
libraryName = config.libraryName,
|
|
140
|
+
componentDescriptors = config.componentDescriptors.orEmpty(),
|
|
141
|
+
cmakeListsPath = config.cmakeListsPath,
|
|
142
|
+
cxxModuleCMakeListsPath = config.cxxModuleCMakeListsPath,
|
|
143
|
+
cxxModuleCMakeListsModuleName = config.cxxModuleCMakeListsModuleName,
|
|
144
|
+
cxxModuleHeaderName = config.cxxModuleHeaderName,
|
|
145
|
+
isPureCxxDependency = config.isPureCxxDependency ?: false,
|
|
146
|
+
includesGeneratedCode = includesGeneratedCode,
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Reads codegenConfig.includesGeneratedCode from module's package.json.
|
|
152
|
+
* Returns false if the file doesn't exist or the flag is not set.
|
|
153
|
+
*/
|
|
154
|
+
private fun readIncludesGeneratedCodeFlag(moduleRootPath: String): Boolean {
|
|
155
|
+
return try {
|
|
156
|
+
val packageJsonFile = java.io.File(moduleRootPath, "package.json")
|
|
157
|
+
if (!packageJsonFile.exists()) return false
|
|
158
|
+
|
|
159
|
+
val content = packageJsonFile.readText()
|
|
160
|
+
val gson = com.google.gson.Gson()
|
|
161
|
+
|
|
162
|
+
@Suppress("UNCHECKED_CAST")
|
|
163
|
+
val json = gson.fromJson(content, Map::class.java) as? Map<String, Any>
|
|
164
|
+
?: return false
|
|
165
|
+
|
|
166
|
+
@Suppress("UNCHECKED_CAST")
|
|
167
|
+
val codegenConfig = json["codegenConfig"] as? Map<String, Any>
|
|
168
|
+
?: return false
|
|
169
|
+
|
|
170
|
+
codegenConfig["includesGeneratedCode"] as? Boolean ?: false
|
|
171
|
+
} catch (e: Exception) {
|
|
172
|
+
// Fail gracefully - treat as false if we can't read the file
|
|
173
|
+
false
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
package run.granite.gradle.tasks
|
|
2
|
+
|
|
3
|
+
import org.gradle.api.DefaultTask
|
|
4
|
+
import org.gradle.api.file.DirectoryProperty
|
|
5
|
+
import org.gradle.api.file.RegularFileProperty
|
|
6
|
+
import org.gradle.api.provider.Property
|
|
7
|
+
import org.gradle.api.tasks.*
|
|
8
|
+
import java.io.File
|
|
9
|
+
import java.util.zip.GZIPOutputStream
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Gradle task for packaging React Native assets and bundles.
|
|
13
|
+
*
|
|
14
|
+
* This task:
|
|
15
|
+
* 1. Copies the JavaScript bundle to Android assets directory
|
|
16
|
+
* 2. Compresses the bundle with gzip (if enabled)
|
|
17
|
+
* 3. Copies React Native drawable assets
|
|
18
|
+
* 4. Organizes assets per build variant
|
|
19
|
+
*
|
|
20
|
+
* The packaged assets are included in the final AAR file.
|
|
21
|
+
*
|
|
22
|
+
* Inputs:
|
|
23
|
+
* - JavaScript bundle file
|
|
24
|
+
* - React Native assets directory
|
|
25
|
+
* - Compression settings
|
|
26
|
+
*
|
|
27
|
+
* Outputs:
|
|
28
|
+
* - Assets in src/{variant}/assets/
|
|
29
|
+
* - Drawable resources in src/{variant}/res/
|
|
30
|
+
*/
|
|
31
|
+
@CacheableTask
|
|
32
|
+
abstract class AssetPackagingTask : DefaultTask() {
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* JavaScript bundle file to package.
|
|
36
|
+
*/
|
|
37
|
+
@get:InputFile
|
|
38
|
+
@get:PathSensitive(PathSensitivity.RELATIVE)
|
|
39
|
+
abstract val bundleFile: RegularFileProperty
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Directory containing React Native drawable assets.
|
|
43
|
+
*/
|
|
44
|
+
@get:InputDirectory
|
|
45
|
+
@get:PathSensitive(PathSensitivity.RELATIVE)
|
|
46
|
+
@get:Optional
|
|
47
|
+
abstract val assetsDir: DirectoryProperty
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Output assets directory (src/{variant}/assets/).
|
|
51
|
+
*/
|
|
52
|
+
@get:OutputDirectory
|
|
53
|
+
abstract val outputAssetsDir: DirectoryProperty
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Output resources directory (src/{variant}/res/).
|
|
57
|
+
*/
|
|
58
|
+
@get:OutputDirectory
|
|
59
|
+
@get:Optional
|
|
60
|
+
abstract val outputResDir: DirectoryProperty
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Bundle asset name (e.g., "index.android.bundle").
|
|
64
|
+
*/
|
|
65
|
+
@get:Input
|
|
66
|
+
abstract val bundleAssetName: Property<String>
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Whether to compress the bundle with gzip.
|
|
70
|
+
*/
|
|
71
|
+
@get:Input
|
|
72
|
+
abstract val compressionEnabled: Property<Boolean>
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Variant name for logging.
|
|
76
|
+
*/
|
|
77
|
+
@get:Input
|
|
78
|
+
abstract val variantName: Property<String>
|
|
79
|
+
|
|
80
|
+
init {
|
|
81
|
+
group = "granite"
|
|
82
|
+
description = "Packages React Native assets and bundles"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@TaskAction
|
|
86
|
+
fun execute() {
|
|
87
|
+
val variant = variantName.get()
|
|
88
|
+
logger.lifecycle("Packaging assets for variant: $variant")
|
|
89
|
+
|
|
90
|
+
// Package JavaScript bundle
|
|
91
|
+
packageBundle()
|
|
92
|
+
|
|
93
|
+
// Package drawable assets
|
|
94
|
+
packageDrawableAssets()
|
|
95
|
+
|
|
96
|
+
logger.lifecycle("Asset packaging complete for variant: $variant")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Packages the JavaScript bundle into the assets directory.
|
|
101
|
+
*
|
|
102
|
+
* If compression is enabled, creates a gzipped bundle file.
|
|
103
|
+
*/
|
|
104
|
+
private fun packageBundle() {
|
|
105
|
+
val bundleSource = bundleFile.get().asFile
|
|
106
|
+
val bundleName = bundleAssetName.get()
|
|
107
|
+
|
|
108
|
+
if (!bundleSource.exists()) {
|
|
109
|
+
error(
|
|
110
|
+
"""
|
|
111
|
+
|Bundle file not found: ${bundleSource.absolutePath}
|
|
112
|
+
|
|
|
113
|
+
|Solution: Ensure the bundle task completed successfully before packaging.
|
|
114
|
+
""".trimMargin(),
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
val outputDir = outputAssetsDir.get().asFile
|
|
119
|
+
outputDir.mkdirs()
|
|
120
|
+
|
|
121
|
+
if (compressionEnabled.get()) {
|
|
122
|
+
// Create gzipped bundle
|
|
123
|
+
val compressedBundle = File(outputDir, "$bundleName.gz")
|
|
124
|
+
logger.lifecycle("Compressing bundle: ${compressedBundle.name}")
|
|
125
|
+
|
|
126
|
+
bundleSource.inputStream().use { input ->
|
|
127
|
+
GZIPOutputStream(compressedBundle.outputStream()).use { gzipOut ->
|
|
128
|
+
input.copyTo(gzipOut)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
logger.lifecycle("Created compressed bundle: ${compressedBundle.absolutePath}")
|
|
133
|
+
} else {
|
|
134
|
+
// Copy bundle without compression
|
|
135
|
+
val outputBundle = File(outputDir, bundleName)
|
|
136
|
+
bundleSource.copyTo(outputBundle, overwrite = true)
|
|
137
|
+
logger.lifecycle("Copied bundle: ${outputBundle.absolutePath}")
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Packages React Native drawable assets into the res directory.
|
|
143
|
+
*
|
|
144
|
+
* Copies drawable-* directories from the assets directory to the Android
|
|
145
|
+
* resources directory for inclusion in the AAR.
|
|
146
|
+
*/
|
|
147
|
+
private fun packageDrawableAssets() {
|
|
148
|
+
if (!assetsDir.isPresent) {
|
|
149
|
+
logger.debug("No assets directory specified, skipping drawable packaging")
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
val assetsSource = assetsDir.get().asFile
|
|
154
|
+
if (!assetsSource.exists()) {
|
|
155
|
+
logger.debug("Assets directory does not exist: ${assetsSource.absolutePath}")
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!outputResDir.isPresent) {
|
|
160
|
+
logger.debug("No output res directory specified, skipping drawable packaging")
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
val outputRes = outputResDir.get().asFile
|
|
165
|
+
outputRes.mkdirs()
|
|
166
|
+
|
|
167
|
+
// Find all drawable-* directories
|
|
168
|
+
val drawableDirs = assetsSource.listFiles { file ->
|
|
169
|
+
file.isDirectory && file.name.startsWith("drawable-")
|
|
170
|
+
} ?: emptyArray()
|
|
171
|
+
|
|
172
|
+
if (drawableDirs.isEmpty()) {
|
|
173
|
+
logger.debug("No drawable directories found in assets")
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Copy each drawable directory
|
|
178
|
+
for (drawableDir in drawableDirs) {
|
|
179
|
+
val targetDir = File(outputRes, drawableDir.name)
|
|
180
|
+
targetDir.mkdirs()
|
|
181
|
+
|
|
182
|
+
drawableDir.walk()
|
|
183
|
+
.filter { it.isFile }
|
|
184
|
+
.forEach { sourceFile ->
|
|
185
|
+
val relativePath = sourceFile.relativeTo(drawableDir).path
|
|
186
|
+
val targetFile = File(targetDir, relativePath)
|
|
187
|
+
targetFile.parentFile.mkdirs()
|
|
188
|
+
sourceFile.copyTo(targetFile, overwrite = true)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
logger.lifecycle("Copied drawable assets: ${drawableDir.name}")
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|