This commit is contained in:
Felitendo
2025-05-20 15:22:07 +02:00
parent c24d95627e
commit 8a6d5d19db
384 changed files with 7065 additions and 4430 deletions

View File

@@ -3,10 +3,11 @@ package com.looker.droidify.index
import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase
import com.fasterxml.jackson.core.JsonToken
import com.looker.droidify.utility.common.extension.Json
import com.looker.droidify.utility.common.extension.asSequence
import com.looker.droidify.utility.common.extension.collectNotNull
import com.looker.droidify.utility.common.extension.writeDictionary
import com.looker.core.common.extension.Json
import com.looker.core.common.extension.asSequence
import com.looker.core.common.extension.collectNotNull
import com.looker.core.common.extension.execWithResult
import com.looker.core.common.extension.writeDictionary
import com.looker.droidify.model.Product
import com.looker.droidify.model.Release
import com.looker.droidify.utility.serialization.product
@@ -82,9 +83,9 @@ class IndexMerger(file: File) : Closeable {
closeTransaction()
db.rawQuery(
"""SELECT product.description, product.data AS pd, releases.data AS rd FROM product
LEFT JOIN releases ON product.package_name = releases.package_name""",
LEFT JOIN releases ON product.package_name = releases.package_name""",
null
).use { cursor ->
)?.use { cursor ->
cursor.asSequence().map { currentCursor ->
val description = currentCursor.getString(0)
val product = Json.factory.createParser(currentCursor.getBlob(1)).use {
@@ -111,8 +112,4 @@ class IndexMerger(file: File) : Closeable {
override fun close() {
db.use { closeTransaction() }
}
private inline fun SQLiteDatabase.execWithResult(sql: String) {
rawQuery(sql, null).use { it.count }
}
}

View File

@@ -5,27 +5,16 @@ import androidx.core.os.ConfigurationCompat.getLocales
import androidx.core.os.LocaleListCompat
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.looker.droidify.utility.common.extension.Json
import com.looker.droidify.utility.common.extension.collectDistinctNotEmptyStrings
import com.looker.droidify.utility.common.extension.collectNotNull
import com.looker.droidify.utility.common.extension.forEach
import com.looker.droidify.utility.common.extension.forEachKey
import com.looker.droidify.utility.common.extension.illegal
import com.looker.core.common.SdkCheck
import com.looker.core.common.extension.Json
import com.looker.core.common.extension.collectDistinctNotEmptyStrings
import com.looker.core.common.extension.collectNotNull
import com.looker.core.common.extension.forEach
import com.looker.core.common.extension.forEachKey
import com.looker.core.common.extension.illegal
import com.looker.core.common.nullIfEmpty
import com.looker.droidify.model.Product
import com.looker.droidify.model.Product.Donate.Bitcoin
import com.looker.droidify.model.Product.Donate.Liberapay
import com.looker.droidify.model.Product.Donate.Litecoin
import com.looker.droidify.model.Product.Donate.OpenCollective
import com.looker.droidify.model.Product.Donate.Regular
import com.looker.droidify.model.Product.Screenshot.Type.LARGE_TABLET
import com.looker.droidify.model.Product.Screenshot.Type.PHONE
import com.looker.droidify.model.Product.Screenshot.Type.SMALL_TABLET
import com.looker.droidify.model.Product.Screenshot.Type.TV
import com.looker.droidify.model.Product.Screenshot.Type.VIDEO
import com.looker.droidify.model.Product.Screenshot.Type.WEAR
import com.looker.droidify.model.Release
import com.looker.droidify.utility.common.SdkCheck
import com.looker.droidify.utility.common.nullIfEmpty
import java.io.InputStream
object IndexV1Parser {
@@ -43,12 +32,9 @@ object IndexV1Parser {
}
private class Screenshots(
val video: List<String>,
val phone: List<String>,
val smallTablet: List<String>,
val largeTablet: List<String>,
val wear: List<String>,
val tv: List<String>,
val largeTablet: List<String>
)
private class Localized(
@@ -104,9 +90,10 @@ object IndexV1Parser {
}
private fun <T> Map<String, Localized>.find(callback: (String, Localized) -> T?): T? {
return getAndCall("en-US", callback)
?: getAndCall("en_US", callback)
?: getAndCall("en", callback)
return getAndCall("en-US", callback) ?: getAndCall("en_US", callback) ?: getAndCall(
"en",
callback
)
}
private fun <T> Map<String, Localized>.findLocalized(callback: (Localized) -> T?): T? {
@@ -135,11 +122,12 @@ object IndexV1Parser {
internal object DonateComparator : Comparator<Product.Donate> {
private val classes = listOf(
Regular::class,
Bitcoin::class,
Litecoin::class,
Liberapay::class,
OpenCollective::class
Product.Donate.Regular::class,
Product.Donate.Bitcoin::class,
Product.Donate.Litecoin::class,
Product.Donate.Flattr::class,
Product.Donate.Liberapay::class,
Product.Donate.OpenCollective::class
)
override fun compare(donate1: Product.Donate, donate2: Product.Donate): Int {
@@ -153,25 +141,14 @@ object IndexV1Parser {
}
}
private const val DICT_REPO = "repo"
private const val DICT_PRODUCT = "apps"
private const val DICT_RELEASE = "packages"
private const val KEY_REPO_ADDRESS = "address"
private const val KEY_REPO_MIRRORS = "mirrors"
private const val KEY_REPO_NAME = "name"
private const val KEY_REPO_DESC = "description"
private const val KEY_REPO_VER = "version"
private const val KEY_REPO_TIME = "timestamp"
fun parse(repositoryId: Long, inputStream: InputStream, callback: Callback) {
val jsonParser = Json.factory.createParser(inputStream)
if (jsonParser.nextToken() != JsonToken.START_OBJECT) {
jsonParser.illegal()
} else {
jsonParser.forEachKey { key ->
jsonParser.forEachKey { it ->
when {
key.dictionary(DICT_REPO) -> {
it.dictionary("repo") -> {
var address = ""
var mirrors = emptyList<String>()
var name = ""
@@ -180,14 +157,12 @@ object IndexV1Parser {
var timestamp = 0L
forEachKey {
when {
it.string(KEY_REPO_ADDRESS) -> address = valueAsString
it.array(KEY_REPO_MIRRORS) -> mirrors =
collectDistinctNotEmptyStrings()
it.string(KEY_REPO_NAME) -> name = valueAsString
it.string(KEY_REPO_DESC) -> description = valueAsString
it.number(KEY_REPO_VER) -> version = valueAsInt
it.number(KEY_REPO_TIME) -> timestamp = valueAsLong
it.string("address") -> address = valueAsString
it.array("mirrors") -> mirrors = collectDistinctNotEmptyStrings()
it.string("name") -> name = valueAsString
it.string("description") -> description = valueAsString
it.number("version") -> version = valueAsInt
it.number("timestamp") -> timestamp = valueAsLong
else -> skipChildren()
}
}
@@ -207,12 +182,12 @@ object IndexV1Parser {
)
}
key.array(DICT_PRODUCT) -> forEach(JsonToken.START_OBJECT) {
it.array("apps") -> forEach(JsonToken.START_OBJECT) {
val product = parseProduct(repositoryId)
callback.onProduct(product)
}
key.dictionary(DICT_RELEASE) -> forEachKey {
it.dictionary("packages") -> forEachKey {
if (it.token == JsonToken.START_ARRAY) {
val packageName = it.key
val releases = collectNotNull(JsonToken.START_OBJECT) { parseRelease() }
@@ -228,38 +203,6 @@ object IndexV1Parser {
}
}
private const val KEY_PRODUCT_PACKAGENAME = "packageName"
private const val KEY_PRODUCT_NAME = "name"
private const val KEY_PRODUCT_SUMMARY = "summary"
private const val KEY_PRODUCT_DESCRIPTION = "description"
private const val KEY_PRODUCT_ICON = "icon"
private const val KEY_PRODUCT_AUTHORNAME = "authorName"
private const val KEY_PRODUCT_AUTHOREMAIL = "authorEmail"
private const val KEY_PRODUCT_AUTHORWEBSITE = "authorWebSite"
private const val KEY_PRODUCT_SOURCECODE = "sourceCode"
private const val KEY_PRODUCT_CHANGELOG = "changelog"
private const val KEY_PRODUCT_WEBSITE = "webSite"
private const val KEY_PRODUCT_ISSUETRACKER = "issueTracker"
private const val KEY_PRODUCT_ADDED = "added"
private const val KEY_PRODUCT_LASTUPDATED = "lastUpdated"
private const val KEY_PRODUCT_SUGGESTEDVERSIONCODE = "suggestedVersionCode"
private const val KEY_PRODUCT_CATEGORIES = "categories"
private const val KEY_PRODUCT_ANTIFEATURES = "antiFeatures"
private const val KEY_PRODUCT_LICENSE = "license"
private const val KEY_PRODUCT_DONATE = "donate"
private const val KEY_PRODUCT_BITCOIN = "bitcoin"
private const val KEY_PRODUCT_LIBERAPAYID = "liberapay"
private const val KEY_PRODUCT_LITECOIN = "litecoin"
private const val KEY_PRODUCT_OPENCOLLECTIVE = "openCollective"
private const val KEY_PRODUCT_LOCALIZED = "localized"
private const val KEY_PRODUCT_WHATSNEW = "whatsNew"
private const val KEY_PRODUCT_PHONE_SCREENSHOTS = "phoneScreenshots"
private const val KEY_PRODUCT_SEVEN_INCH_SCREENSHOTS = "sevenInchScreenshots"
private const val KEY_PRODUCT_TEN_INCH_SCREENSHOTS = "tenInchScreenshots"
private const val KEY_PRODUCT_WEAR_SCREENSHOTS = "wearScreenshots"
private const val KEY_PRODUCT_TV_SCREENSHOTS = "tvScreenshots"
private const val KEY_PRODUCT_VIDEO = "video"
private fun JsonParser.parseProduct(repositoryId: Long): Product {
var packageName = ""
var nameFallback = ""
@@ -281,42 +224,42 @@ object IndexV1Parser {
val licenses = mutableListOf<String>()
val donates = mutableListOf<Product.Donate>()
val localizedMap = mutableMapOf<String, Localized>()
forEachKey { key ->
forEachKey { it ->
when {
key.string(KEY_PRODUCT_PACKAGENAME) -> packageName = valueAsString
key.string(KEY_PRODUCT_NAME) -> nameFallback = valueAsString
key.string(KEY_PRODUCT_SUMMARY) -> summaryFallback = valueAsString
key.string(KEY_PRODUCT_DESCRIPTION) -> descriptionFallback = valueAsString
key.string(KEY_PRODUCT_ICON) -> icon = validateIcon(valueAsString)
key.string(KEY_PRODUCT_AUTHORNAME) -> authorName = valueAsString
key.string(KEY_PRODUCT_AUTHOREMAIL) -> authorEmail = valueAsString
key.string(KEY_PRODUCT_AUTHORWEBSITE) -> authorWeb = valueAsString
key.string(KEY_PRODUCT_SOURCECODE) -> source = valueAsString
key.string(KEY_PRODUCT_CHANGELOG) -> changelog = valueAsString
key.string(KEY_PRODUCT_WEBSITE) -> web = valueAsString
key.string(KEY_PRODUCT_ISSUETRACKER) -> tracker = valueAsString
key.number(KEY_PRODUCT_ADDED) -> added = valueAsLong
key.number(KEY_PRODUCT_LASTUPDATED) -> updated = valueAsLong
key.string(KEY_PRODUCT_SUGGESTEDVERSIONCODE) ->
it.string("packageName") -> packageName = valueAsString
it.string("name") -> nameFallback = valueAsString
it.string("summary") -> summaryFallback = valueAsString
it.string("description") -> descriptionFallback = valueAsString
it.string("icon") -> icon = validateIcon(valueAsString)
it.string("authorName") -> authorName = valueAsString
it.string("authorEmail") -> authorEmail = valueAsString
it.string("authorWebSite") -> authorWeb = valueAsString
it.string("sourceCode") -> source = valueAsString
it.string("changelog") -> changelog = valueAsString
it.string("webSite") -> web = valueAsString
it.string("issueTracker") -> tracker = valueAsString
it.number("added") -> added = valueAsLong
it.number("lastUpdated") -> updated = valueAsLong
it.string("suggestedVersionCode") ->
suggestedVersionCode =
valueAsString.toLongOrNull() ?: 0L
key.array(KEY_PRODUCT_CATEGORIES) -> categories = collectDistinctNotEmptyStrings()
key.array(KEY_PRODUCT_ANTIFEATURES) -> antiFeatures =
collectDistinctNotEmptyStrings()
key.string(KEY_PRODUCT_LICENSE) -> licenses += valueAsString.split(',')
it.array("categories") -> categories = collectDistinctNotEmptyStrings()
it.array("antiFeatures") -> antiFeatures = collectDistinctNotEmptyStrings()
it.string("license") -> licenses += valueAsString.split(',')
.filter { it.isNotEmpty() }
key.string(KEY_PRODUCT_DONATE) -> donates += Regular(valueAsString)
key.string(KEY_PRODUCT_BITCOIN) -> donates += Bitcoin(valueAsString)
key.string(KEY_PRODUCT_LIBERAPAYID) -> donates += Liberapay(valueAsString)
key.string(KEY_PRODUCT_LITECOIN) -> donates += Litecoin(valueAsString)
key.string(KEY_PRODUCT_OPENCOLLECTIVE) -> donates += OpenCollective(valueAsString)
it.string("donate") -> donates += Product.Donate.Regular(valueAsString)
it.string("bitcoin") -> donates += Product.Donate.Bitcoin(valueAsString)
it.string("flattrID") -> donates += Product.Donate.Flattr(valueAsString)
it.string("liberapayID") -> donates += Product.Donate.Liberapay(valueAsString)
it.string("openCollective") -> donates += Product.Donate.OpenCollective(
valueAsString
)
key.dictionary(KEY_PRODUCT_LOCALIZED) -> forEachKey { localizedKey ->
if (localizedKey.token == JsonToken.START_OBJECT) {
val locale = localizedKey.key
it.dictionary("localized") -> forEachKey { it ->
if (it.token == JsonToken.START_OBJECT) {
val locale = it.key
var name = ""
var summary = ""
var description = ""
@@ -325,52 +268,46 @@ object IndexV1Parser {
var phone = emptyList<String>()
var smallTablet = emptyList<String>()
var largeTablet = emptyList<String>()
var wear = emptyList<String>()
var tv = emptyList<String>()
var video = emptyList<String>()
forEachKey {
when {
it.string(KEY_PRODUCT_NAME) -> name = valueAsString
it.string(KEY_PRODUCT_SUMMARY) -> summary = valueAsString
it.string(KEY_PRODUCT_DESCRIPTION) -> description = valueAsString
it.string(KEY_PRODUCT_WHATSNEW) -> whatsNew = valueAsString
it.string(KEY_PRODUCT_ICON) -> metadataIcon = valueAsString
it.string(KEY_PRODUCT_VIDEO) -> video = listOf(valueAsString)
it.array(KEY_PRODUCT_PHONE_SCREENSHOTS) ->
phone = collectDistinctNotEmptyStrings()
it.string("name") -> name = valueAsString
it.string("summary") -> summary = valueAsString
it.string("description") -> description = valueAsString
it.string("whatsNew") -> whatsNew = valueAsString
it.string("icon") -> metadataIcon = valueAsString
it.array("phoneScreenshots") ->
phone =
collectDistinctNotEmptyStrings()
it.array(KEY_PRODUCT_SEVEN_INCH_SCREENSHOTS) ->
smallTablet = collectDistinctNotEmptyStrings()
it.array("sevenInchScreenshots") ->
smallTablet =
collectDistinctNotEmptyStrings()
it.array(KEY_PRODUCT_TEN_INCH_SCREENSHOTS) ->
largeTablet = collectDistinctNotEmptyStrings()
it.array(KEY_PRODUCT_WEAR_SCREENSHOTS) ->
wear = collectDistinctNotEmptyStrings()
it.array(KEY_PRODUCT_TV_SCREENSHOTS) ->
tv = collectDistinctNotEmptyStrings()
it.array("tenInchScreenshots") ->
largeTablet =
collectDistinctNotEmptyStrings()
else -> skipChildren()
}
}
val isScreenshotEmpty =
arrayOf(video, phone, smallTablet, largeTablet, wear, tv)
.any { it.isNotEmpty() }
val screenshots =
if (isScreenshotEmpty) {
Screenshots(video, phone, smallTablet, largeTablet, wear, tv)
if (sequenceOf(
phone,
smallTablet,
largeTablet
).any { it.isNotEmpty() }
) {
Screenshots(phone, smallTablet, largeTablet)
} else {
null
}
localizedMap[locale] = Localized(
name = name,
summary = summary,
description = description,
whatsNew = whatsNew,
metadataIcon = metadataIcon.nullIfEmpty()?.let { "$locale/$it" }
.orEmpty(),
screenshots = screenshots,
name,
summary,
description,
whatsNew,
metadataIcon.nullIfEmpty()?.let { "$locale/$it" }.orEmpty(),
screenshots
)
} else {
skipChildren()
@@ -393,61 +330,54 @@ object IndexV1Parser {
}
val screenshotPairs =
localizedMap.find { key, localized -> localized.screenshots?.let { Pair(key, it) } }
val screenshots = screenshotPairs?.let { (key, screenshots) ->
screenshots.video.map { Product.Screenshot(key, VIDEO, it) } +
screenshots.phone.map { Product.Screenshot(key, PHONE, it) } +
screenshots.smallTablet.map { Product.Screenshot(key, SMALL_TABLET, it) } +
screenshots.largeTablet.map { Product.Screenshot(key, LARGE_TABLET, it) } +
screenshots.wear.map { Product.Screenshot(key, WEAR, it) } +
screenshots.tv.map { Product.Screenshot(key, TV, it) }
}.orEmpty()
val screenshots = screenshotPairs
?.let { (key, screenshots) ->
screenshots.phone.asSequence()
.map { Product.Screenshot(key, Product.Screenshot.Type.PHONE, it) } +
screenshots.smallTablet.asSequence()
.map {
Product.Screenshot(
key,
Product.Screenshot.Type.SMALL_TABLET,
it
)
} +
screenshots.largeTablet.asSequence()
.map {
Product.Screenshot(
key,
Product.Screenshot.Type.LARGE_TABLET,
it
)
}
}
.orEmpty().toList()
return Product(
repositoryId = repositoryId,
packageName = packageName,
name = name,
summary = summary,
description = description,
whatsNew = whatsNew,
icon = icon,
metadataIcon = metadataIcon,
author = Product.Author(authorName, authorEmail, authorWeb),
source = source,
changelog = changelog,
web = web,
tracker = tracker,
added = added,
updated = updated,
suggestedVersionCode = suggestedVersionCode,
categories = categories,
antiFeatures = antiFeatures,
licenses = licenses,
donates = donates.sortedWith(DonateComparator),
screenshots = screenshots,
releases = emptyList()
repositoryId,
packageName,
name,
summary,
description,
whatsNew,
icon,
metadataIcon,
Product.Author(authorName, authorEmail, authorWeb),
source,
changelog,
web,
tracker,
added,
updated,
suggestedVersionCode,
categories,
antiFeatures,
licenses,
donates.sortedWith(DonateComparator),
screenshots,
emptyList()
)
}
private const val KEY_RELEASE_VERSIONNAME = "versionName"
private const val KEY_RELEASE_VERSIONCODE = "versionCode"
private const val KEY_RELEASE_ADDED = "added"
private const val KEY_RELEASE_SIZE = "size"
private const val KEY_RELEASE_MINSDKVERSION = "minSdkVersion"
private const val KEY_RELEASE_TARGETSDKVERSION = "targetSdkVersion"
private const val KEY_RELEASE_MAXSDKVERSION = "maxSdkVersion"
private const val KEY_RELEASE_SRCNAME = "srcname"
private const val KEY_RELEASE_APKNAME = "apkName"
private const val KEY_RELEASE_HASH = "hash"
private const val KEY_RELEASE_HASHTYPE = "hashType"
private const val KEY_RELEASE_SIG = "sig"
private const val KEY_RELEASE_OBBMAINFILE = "obbMainFile"
private const val KEY_RELEASE_OBBMAINFILESHA256 = "obbMainFileSha256"
private const val KEY_RELEASE_OBBPATCHFILE = "obbPatchFile"
private const val KEY_RELEASE_OBBPATCHFILESHA256 = "obbPatchFileSha256"
private const val KEY_RELEASE_USESPERMISSION = "uses-permission"
private const val KEY_RELEASE_USESPERMISSIONSDK23 = "uses-permission-sdk-23"
private const val KEY_RELEASE_FEATURES = "features"
private const val KEY_RELEASE_NATIVECODE = "nativecode"
private fun JsonParser.parseRelease(): Release {
var version = ""
var versionCode = 0L
@@ -468,28 +398,28 @@ object IndexV1Parser {
val permissions = linkedSetOf<String>()
var features = emptyList<String>()
var platforms = emptyList<String>()
forEachKey { key ->
forEachKey {
when {
key.string(KEY_RELEASE_VERSIONNAME) -> version = valueAsString
key.number(KEY_RELEASE_VERSIONCODE) -> versionCode = valueAsLong
key.number(KEY_RELEASE_ADDED) -> added = valueAsLong
key.number(KEY_RELEASE_SIZE) -> size = valueAsLong
key.number(KEY_RELEASE_MINSDKVERSION) -> minSdkVersion = valueAsInt
key.number(KEY_RELEASE_TARGETSDKVERSION) -> targetSdkVersion = valueAsInt
key.number(KEY_RELEASE_MAXSDKVERSION) -> maxSdkVersion = valueAsInt
key.string(KEY_RELEASE_SRCNAME) -> source = valueAsString
key.string(KEY_RELEASE_APKNAME) -> release = valueAsString
key.string(KEY_RELEASE_HASH) -> hash = valueAsString
key.string(KEY_RELEASE_HASHTYPE) -> hashTypeCandidate = valueAsString
key.string(KEY_RELEASE_SIG) -> signature = valueAsString
key.string(KEY_RELEASE_OBBMAINFILE) -> obbMain = valueAsString
key.string(KEY_RELEASE_OBBMAINFILESHA256) -> obbMainHash = valueAsString
key.string(KEY_RELEASE_OBBPATCHFILE) -> obbPatch = valueAsString
key.string(KEY_RELEASE_OBBPATCHFILESHA256) -> obbPatchHash = valueAsString
key.array(KEY_RELEASE_USESPERMISSION) -> collectPermissions(permissions, 0)
key.array(KEY_RELEASE_USESPERMISSIONSDK23) -> collectPermissions(permissions, 23)
key.array(KEY_RELEASE_FEATURES) -> features = collectDistinctNotEmptyStrings()
key.array(KEY_RELEASE_NATIVECODE) -> platforms = collectDistinctNotEmptyStrings()
it.string("versionName") -> version = valueAsString
it.number("versionCode") -> versionCode = valueAsLong
it.number("added") -> added = valueAsLong
it.number("size") -> size = valueAsLong
it.number("minSdkVersion") -> minSdkVersion = valueAsInt
it.number("targetSdkVersion") -> targetSdkVersion = valueAsInt
it.number("maxSdkVersion") -> maxSdkVersion = valueAsInt
it.string("srcname") -> source = valueAsString
it.string("apkName") -> release = valueAsString
it.string("hash") -> hash = valueAsString
it.string("hashType") -> hashTypeCandidate = valueAsString
it.string("sig") -> signature = valueAsString
it.string("obbMainFile") -> obbMain = valueAsString
it.string("obbMainFileSha256") -> obbMainHash = valueAsString
it.string("obbPatchFile") -> obbPatch = valueAsString
it.string("obbPatchFileSha256") -> obbPatchHash = valueAsString
it.array("uses-permission") -> collectPermissions(permissions, 0)
it.array("uses-permission-sdk-23") -> collectPermissions(permissions, 23)
it.array("features") -> features = collectDistinctNotEmptyStrings()
it.array("nativecode") -> platforms = collectDistinctNotEmptyStrings()
else -> skipChildren()
}
}
@@ -498,29 +428,29 @@ object IndexV1Parser {
val obbMainHashType = if (obbMainHash.isNotEmpty()) "sha256" else ""
val obbPatchHashType = if (obbPatchHash.isNotEmpty()) "sha256" else ""
return Release(
selected = false,
version = version,
versionCode = versionCode,
added = added,
size = size,
minSdkVersion = minSdkVersion,
targetSdkVersion = targetSdkVersion,
maxSdkVersion = maxSdkVersion,
source = source,
release = release,
hash = hash,
hashType = hashType,
signature = signature,
obbMain = obbMain,
obbMainHash = obbMainHash,
obbMainHashType = obbMainHashType,
obbPatch = obbPatch,
obbPatchHash = obbPatchHash,
obbPatchHashType = obbPatchHashType,
permissions = permissions.toList(),
features = features,
platforms = platforms,
incompatibilities = emptyList()
false,
version,
versionCode,
added,
size,
minSdkVersion,
targetSdkVersion,
maxSdkVersion,
source,
release,
hash,
hashType,
signature,
obbMain,
obbMainHash,
obbMainHashType,
obbPatch,
obbPatchHash,
obbPatchHashType,
permissions.toList(),
features,
platforms,
emptyList()
)
}

View File

@@ -2,28 +2,28 @@ package com.looker.droidify.index
import android.content.Context
import android.net.Uri
import com.looker.droidify.database.Database
import com.looker.droidify.domain.model.fingerprint
import com.looker.core.common.SdkCheck
import com.looker.core.common.cache.Cache
import com.looker.core.common.extension.fingerprint
import com.looker.core.common.extension.toFormattedString
import com.looker.core.common.result.Result
import com.looker.droidify.model.Product
import com.looker.droidify.model.Release
import com.looker.droidify.model.Repository
import com.looker.droidify.network.Downloader
import com.looker.droidify.network.NetworkResponse
import com.looker.droidify.utility.common.SdkCheck
import com.looker.droidify.utility.common.cache.Cache
import com.looker.droidify.utility.common.extension.toFormattedString
import com.looker.droidify.utility.common.result.Result
import com.looker.droidify.database.Database
import com.looker.droidify.utility.extension.android.Android
import com.looker.droidify.utility.getProgress
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import com.looker.network.Downloader
import com.looker.network.NetworkResponse
import java.io.File
import java.security.CodeSigner
import java.security.cert.Certificate
import java.util.jar.JarEntry
import java.util.jar.JarFile
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
object RepositoryUpdater {
enum class Stage {
@@ -31,7 +31,7 @@ object RepositoryUpdater {
}
// TODO Add support for Index-V2 and also cleanup everything here
enum class IndexType(
private enum class IndexType(
val jarName: String,
val contentName: String
) {
@@ -219,13 +219,12 @@ object RepositoryUpdater {
}
}
fun processFile(
private fun processFile(
context: Context,
repository: Repository,
indexType: IndexType,
unstable: Boolean,
file: File,
mergerFile: File = Cache.getTemporaryFile(context),
lastModified: String,
entityTag: String,
callback: (Stage, Long, Long?) -> Unit
@@ -242,6 +241,7 @@ object RepositoryUpdater {
var changedRepository: Repository? = null
val mergerFile = Cache.getTemporaryFile(context)
try {
val unmergedProducts = mutableListOf<Product>()
val unmergedReleases = mutableListOf<Pair<String, List<Release>>>()
@@ -344,7 +344,6 @@ object RepositoryUpdater {
.codeSigner
.certificate
.fingerprint()
.toString()
.uppercase()
val commitRepository = if (!workRepository.fingerprint.equals(