package expo.modules.updates.manifest import android.net.Uri import android.util.Log import expo.modules.jsonutils.getNullable import expo.modules.updates.UpdatesConfiguration import expo.modules.updates.db.entity.AssetEntity import expo.modules.updates.db.entity.UpdateEntity import expo.modules.updates.db.enums.UpdateStatus import expo.modules.updates.loader.EmbeddedLoader import expo.modules.manifests.core.EmbeddedManifest import org.json.JSONArray import org.json.JSONException import java.util.* /** * Class for bare-bones manifests embedded in application packages. These manifest objects are * generated by the script at expo-updates/scripts/createManifest.js and describe the update * embedded by react-native in the application package. They contain the minimum amount of * information needed to reliably identify the update and insert it into [UpdatesDatabase]. */ class EmbeddedUpdate private constructor( override val manifest: EmbeddedManifest, private val id: UUID, private val scopeKey: String, private val commitTime: Date, private val runtimeVersion: String, private val assets: JSONArray?, private val url: Uri, private val requestHeaders: Map ) : Update { override val updateEntity: UpdateEntity by lazy { UpdateEntity(id, commitTime, runtimeVersion, scopeKey, this@EmbeddedUpdate.manifest.getRawJson(), url, requestHeaders).apply { status = UpdateStatus.EMBEDDED } } override val assetEntityList: List by lazy { val assetList = mutableListOf() val bundleKey = "bundle-$id" val bundleAssetEntity = AssetEntity(bundleKey, "js").apply { isLaunchAsset = true embeddedAssetFilename = EmbeddedLoader.BARE_BUNDLE_FILENAME } assetList.add(bundleAssetEntity) if (assets != null && assets.length() > 0) { for (i in 0 until assets.length()) { try { val assetObject = assets.getJSONObject(i) val type = assetObject.getString("type") val assetEntity = AssetEntity( assetObject.getString("packagerHash"), type ).apply { resourcesFilename = assetObject.getNullable("resourcesFilename") resourcesFolder = assetObject.getNullable("resourcesFolder") } val scales = assetObject.getNullable("scales") // if there's only one scale we don't to decide later on which one to copy // so we avoid this work now if (scales != null && scales.length() > 1) { assetEntity.scale = assetObject.optDouble("scale").toFloat() val scalesTemp = Array(scales.length()) { 0f } for (j in 0 until scales.length()) { scalesTemp[j] = scales.getDouble(j).toFloat() } assetEntity.scales = scalesTemp } assetList.add(assetEntity) } catch (e: JSONException) { Log.e(TAG, "Could not read asset from manifest", e) } } } assetList } override val isDevelopmentMode: Boolean = false companion object { private val TAG = EmbeddedUpdate::class.java.simpleName @Throws(JSONException::class) fun fromEmbeddedManifest( manifest: EmbeddedManifest, configuration: UpdatesConfiguration ): EmbeddedUpdate = EmbeddedUpdate( manifest, id = UUID.fromString(manifest.getID()), configuration.scopeKey, commitTime = Date(manifest.getCommitTimeLong()), runtimeVersion = configuration.getRuntimeVersion(), assets = manifest.getAssets(), url = configuration.originalEmbeddedUpdateUrl, requestHeaders = configuration.originalEmbeddedRequestHeaders ) } }