mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-06-19 13:59:19 +00:00
Rename package to com.machaiv3lli.fdroid
This commit is contained in:
101
src/main/kotlin/com/machiav3lli/fdroid/database/Converters.kt
Normal file
101
src/main/kotlin/com/machiav3lli/fdroid/database/Converters.kt
Normal file
@ -0,0 +1,101 @@
|
||||
package com.machiav3lli.fdroid.database
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.machiav3lli.fdroid.database.entity.Release
|
||||
import com.machiav3lli.fdroid.entity.Author
|
||||
import com.machiav3lli.fdroid.entity.Donate
|
||||
import com.machiav3lli.fdroid.entity.Screenshot
|
||||
|
||||
object Converters {
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toStringList(byteArray: ByteArray): List<String> {
|
||||
val string = String(byteArray)
|
||||
return if (string == "") emptyList()
|
||||
else string.removeSurrounding("[", "]").split(", ").filter(String::isNotEmpty)
|
||||
}
|
||||
|
||||
@JvmName("stringListToByteArray")
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toByteArray(list: List<String>): ByteArray = list.toString().toByteArray()
|
||||
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toPairStringList(byteArray: ByteArray): List<Pair<String, String>> {
|
||||
val string = String(byteArray)
|
||||
return if (string == "") emptyList()
|
||||
else string.removeSurrounding("[", "]").split(",").filter(String::isNotEmpty).mapNotNull {
|
||||
val pairs = it.split("|")
|
||||
if (pairs.size == 2) Pair(pairs[0], pairs[1])
|
||||
else null
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("pairStringListToByteArray")
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toByteArray(list: List<Pair<String, String>>): ByteArray =
|
||||
list.map { it.toList().joinToString("|") }.toString().toByteArray()
|
||||
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toAuthor(byteArray: ByteArray) = Author.fromJson(String(byteArray))
|
||||
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toByteArray(author: Author) = author.toJSON().toByteArray()
|
||||
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toReleases(byteArray: ByteArray): List<Release> =
|
||||
if (String(byteArray) == "") emptyList()
|
||||
else String(byteArray).split("|").map { Release.fromJson(it) }
|
||||
|
||||
@JvmName("releasesToByteArray")
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toByteArray(releases: List<Release>) =
|
||||
if (releases.isNotEmpty()) releases.joinToString("|") { it.toJSON() }.toByteArray()
|
||||
else "".toByteArray()
|
||||
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toIncompatibilities(byteArray: ByteArray): List<Release.Incompatibility> =
|
||||
if (String(byteArray) == "") emptyList()
|
||||
else String(byteArray).split("|").map { Release.Incompatibility.fromJson(it) }
|
||||
|
||||
@JvmName("incompatibilitiesToByteArray")
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toByteArray(incompatibilities: List<Release.Incompatibility>) =
|
||||
if (incompatibilities.isNotEmpty())
|
||||
incompatibilities.joinToString("|") { it.toJSON() }.toByteArray()
|
||||
else "".toByteArray()
|
||||
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toScreenshots(byteArray: ByteArray): List<Screenshot> =
|
||||
if (String(byteArray) == "") emptyList()
|
||||
else String(byteArray).split("|").map { Screenshot.fromJson(it) }
|
||||
|
||||
@JvmName("screenshotsToByteArray")
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toByteArray(screenshots: List<Screenshot>) =
|
||||
if (screenshots.isNotEmpty()) screenshots.joinToString("|") { it.toJSON() }.toByteArray()
|
||||
else "".toByteArray()
|
||||
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toDonates(byteArray: ByteArray): List<Donate> =
|
||||
if (String(byteArray) == "") emptyList()
|
||||
else String(byteArray).split("|").map { Donate.fromJson(it) }
|
||||
|
||||
@JvmName("donatesToByteArray")
|
||||
@TypeConverter
|
||||
@JvmStatic
|
||||
fun toByteArray(donates: List<Donate>) =
|
||||
if (donates.isNotEmpty()) donates.joinToString("|") { it.toJSON() }.toByteArray()
|
||||
else "".toByteArray()
|
||||
}
|
110
src/main/kotlin/com/machiav3lli/fdroid/database/DatabaseX.kt
Normal file
110
src/main/kotlin/com/machiav3lli/fdroid/database/DatabaseX.kt
Normal file
@ -0,0 +1,110 @@
|
||||
package com.machiav3lli.fdroid.database
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import com.machiav3lli.fdroid.database.dao.CategoryDao
|
||||
import com.machiav3lli.fdroid.database.dao.CategoryTempDao
|
||||
import com.machiav3lli.fdroid.database.dao.ExtrasDao
|
||||
import com.machiav3lli.fdroid.database.dao.InstalledDao
|
||||
import com.machiav3lli.fdroid.database.dao.ProductDao
|
||||
import com.machiav3lli.fdroid.database.dao.ProductTempDao
|
||||
import com.machiav3lli.fdroid.database.dao.ReleaseDao
|
||||
import com.machiav3lli.fdroid.database.dao.RepositoryDao
|
||||
import com.machiav3lli.fdroid.database.entity.Category
|
||||
import com.machiav3lli.fdroid.database.entity.CategoryTemp
|
||||
import com.machiav3lli.fdroid.database.entity.Extras
|
||||
import com.machiav3lli.fdroid.database.entity.Installed
|
||||
import com.machiav3lli.fdroid.database.entity.Product
|
||||
import com.machiav3lli.fdroid.database.entity.ProductTemp
|
||||
import com.machiav3lli.fdroid.database.entity.Release
|
||||
import com.machiav3lli.fdroid.database.entity.Repository
|
||||
import com.machiav3lli.fdroid.database.entity.Repository.Companion.defaultRepositories
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
Repository::class,
|
||||
Product::class,
|
||||
Release::class,
|
||||
ProductTemp::class,
|
||||
Category::class,
|
||||
CategoryTemp::class,
|
||||
Installed::class,
|
||||
Extras::class
|
||||
], version = 8
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class DatabaseX : RoomDatabase() {
|
||||
abstract val repositoryDao: RepositoryDao
|
||||
abstract val productDao: ProductDao
|
||||
abstract val releaseDao: ReleaseDao
|
||||
abstract val productTempDao: ProductTempDao
|
||||
abstract val categoryDao: CategoryDao
|
||||
abstract val categoryTempDao: CategoryTempDao
|
||||
abstract val installedDao: InstalledDao
|
||||
abstract val extrasDao: ExtrasDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var INSTANCE: DatabaseX? = null
|
||||
|
||||
fun getInstance(context: Context): DatabaseX {
|
||||
synchronized(this) {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = Room
|
||||
.databaseBuilder(
|
||||
context.applicationContext,
|
||||
DatabaseX::class.java,
|
||||
"main_database.db"
|
||||
)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
INSTANCE?.let { instance ->
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
if (instance.repositoryDao.count == 0) defaultRepositories.forEach {
|
||||
instance.repositoryDao.put(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun cleanUp(pairs: Set<Pair<Long, Boolean>>) {
|
||||
runInTransaction {
|
||||
pairs.windowed(10, 10, true).map {
|
||||
it.map { it.first }
|
||||
.toLongArray()
|
||||
.forEach { id ->
|
||||
productDao.deleteById(id)
|
||||
categoryDao.deleteById(id)
|
||||
}
|
||||
it.filter { it.second }
|
||||
.map { it.first }
|
||||
.toLongArray()
|
||||
.forEach { id -> repositoryDao.deleteById(id) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun finishTemporary(repository: Repository, success: Boolean) {
|
||||
runInTransaction {
|
||||
if (success) {
|
||||
productDao.deleteById(repository.id)
|
||||
categoryDao.deleteById(repository.id)
|
||||
productDao.insert(*(productTempDao.all))
|
||||
categoryDao.insert(*(categoryTempDao.all))
|
||||
repositoryDao.put(repository)
|
||||
}
|
||||
productTempDao.emptyTable()
|
||||
categoryTempDao.emptyTable()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.machiav3lli.fdroid.database
|
||||
|
||||
class QueryBuilder {
|
||||
companion object {
|
||||
fun trimQuery(query: String): String {
|
||||
return query.lines().map { it.trim() }.filter { it.isNotEmpty() }
|
||||
.joinToString(separator = " ")
|
||||
}
|
||||
}
|
||||
|
||||
private val builder = StringBuilder()
|
||||
val arguments = mutableListOf<String>()
|
||||
|
||||
operator fun plusAssign(query: String) {
|
||||
if (builder.isNotEmpty()) {
|
||||
builder.append(" ")
|
||||
}
|
||||
builder.append(trimQuery(query))
|
||||
}
|
||||
|
||||
operator fun remAssign(argument: String) {
|
||||
this.arguments += argument
|
||||
}
|
||||
|
||||
operator fun remAssign(arguments: List<String>) {
|
||||
this.arguments += arguments
|
||||
}
|
||||
|
||||
fun build() = builder.toString()
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.machiav3lli.fdroid.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
|
||||
interface BaseDao<T> {
|
||||
@Insert
|
||||
fun insert(vararg product: T)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertReplace(vararg product: T)
|
||||
|
||||
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun update(vararg obj: T): Int
|
||||
|
||||
@Delete
|
||||
fun delete(obj: T)
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.machiav3lli.fdroid.database.dao
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.machiav3lli.fdroid.database.entity.Category
|
||||
import com.machiav3lli.fdroid.database.entity.CategoryTemp
|
||||
|
||||
@Dao
|
||||
interface CategoryDao : BaseDao<Category> {
|
||||
@get:Query(
|
||||
"""SELECT DISTINCT category.label
|
||||
FROM category AS category
|
||||
JOIN repository AS repository
|
||||
ON category.repositoryId = repository._id
|
||||
WHERE repository.enabled != 0"""
|
||||
)
|
||||
val allNames: List<String>
|
||||
|
||||
@get:Query(
|
||||
"""SELECT DISTINCT category.label
|
||||
FROM category AS category
|
||||
JOIN repository AS repository
|
||||
ON category.repositoryId = repository._id
|
||||
WHERE repository.enabled != 0"""
|
||||
)
|
||||
val allNamesLive: LiveData<List<String>>
|
||||
|
||||
@Query("DELETE FROM category WHERE repositoryId = :id")
|
||||
fun deleteById(id: Long): Int
|
||||
}
|
||||
|
||||
@Dao
|
||||
interface CategoryTempDao : BaseDao<CategoryTemp> {
|
||||
@get:Query("SELECT * FROM temporary_category")
|
||||
val all: Array<CategoryTemp>
|
||||
|
||||
@Query("DELETE FROM temporary_category")
|
||||
fun emptyTable()
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.machiav3lli.fdroid.database.dao
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.machiav3lli.fdroid.database.entity.Installed
|
||||
|
||||
// TODO make sure that apps that not uninstalled by Droid-ify still get removed
|
||||
@Dao
|
||||
interface InstalledDao : BaseDao<Installed> {
|
||||
fun put(vararg installed: Installed) {
|
||||
installed.forEach { insertReplace(it) }
|
||||
}
|
||||
|
||||
@get:Query("SELECT * FROM memory_installed")
|
||||
val allLive: LiveData<List<Installed>>
|
||||
|
||||
@Query("SELECT * FROM memory_installed WHERE packageName = :packageName")
|
||||
fun get(packageName: String): Installed?
|
||||
|
||||
@Query("SELECT * FROM memory_installed WHERE packageName = :packageName")
|
||||
fun getLive(packageName: String): LiveData<Installed?>
|
||||
|
||||
@Query("DELETE FROM memory_installed WHERE packageName = :packageName")
|
||||
fun delete(packageName: String)
|
||||
|
||||
@Query("DELETE FROM memory_installed")
|
||||
fun emptyTable()
|
||||
}
|
@ -0,0 +1,277 @@
|
||||
package com.machiav3lli.fdroid.database.dao
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.RawQuery
|
||||
import androidx.room.Transaction
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||
import androidx.sqlite.db.SupportSQLiteQuery
|
||||
import com.machiav3lli.fdroid.ROW_ADDED
|
||||
import com.machiav3lli.fdroid.ROW_ANTIFEATURES
|
||||
import com.machiav3lli.fdroid.ROW_CAN_UPDATE
|
||||
import com.machiav3lli.fdroid.ROW_CATEGORIES
|
||||
import com.machiav3lli.fdroid.ROW_COMPATIBLE
|
||||
import com.machiav3lli.fdroid.ROW_DESCRIPTION
|
||||
import com.machiav3lli.fdroid.ROW_DONATES
|
||||
import com.machiav3lli.fdroid.ROW_ENABLED
|
||||
import com.machiav3lli.fdroid.ROW_ICON
|
||||
import com.machiav3lli.fdroid.ROW_ID
|
||||
import com.machiav3lli.fdroid.ROW_IGNORED_VERSION
|
||||
import com.machiav3lli.fdroid.ROW_IGNORE_UPDATES
|
||||
import com.machiav3lli.fdroid.ROW_LABEL
|
||||
import com.machiav3lli.fdroid.ROW_LICENSES
|
||||
import com.machiav3lli.fdroid.ROW_MATCH_RANK
|
||||
import com.machiav3lli.fdroid.ROW_METADATA_ICON
|
||||
import com.machiav3lli.fdroid.ROW_PACKAGE_NAME
|
||||
import com.machiav3lli.fdroid.ROW_RELEASES
|
||||
import com.machiav3lli.fdroid.ROW_REPOSITORY_ID
|
||||
import com.machiav3lli.fdroid.ROW_SCREENSHOTS
|
||||
import com.machiav3lli.fdroid.ROW_SIGNATURE
|
||||
import com.machiav3lli.fdroid.ROW_SIGNATURES
|
||||
import com.machiav3lli.fdroid.ROW_SUMMARY
|
||||
import com.machiav3lli.fdroid.ROW_UPDATED
|
||||
import com.machiav3lli.fdroid.ROW_VERSION_CODE
|
||||
import com.machiav3lli.fdroid.TABLE_CATEGORY
|
||||
import com.machiav3lli.fdroid.TABLE_CATEGORY_NAME
|
||||
import com.machiav3lli.fdroid.TABLE_EXTRAS
|
||||
import com.machiav3lli.fdroid.TABLE_EXTRAS_NAME
|
||||
import com.machiav3lli.fdroid.TABLE_INSTALLED
|
||||
import com.machiav3lli.fdroid.TABLE_INSTALLED_NAME
|
||||
import com.machiav3lli.fdroid.TABLE_PRODUCT
|
||||
import com.machiav3lli.fdroid.TABLE_PRODUCT_NAME
|
||||
import com.machiav3lli.fdroid.TABLE_REPOSITORY
|
||||
import com.machiav3lli.fdroid.TABLE_REPOSITORY_NAME
|
||||
import com.machiav3lli.fdroid.database.QueryBuilder
|
||||
import com.machiav3lli.fdroid.database.entity.CategoryTemp
|
||||
import com.machiav3lli.fdroid.database.entity.Extras
|
||||
import com.machiav3lli.fdroid.database.entity.Product
|
||||
import com.machiav3lli.fdroid.database.entity.ProductTemp
|
||||
import com.machiav3lli.fdroid.database.entity.asProductTemp
|
||||
import com.machiav3lli.fdroid.entity.Order
|
||||
import com.machiav3lli.fdroid.entity.Section
|
||||
import com.machiav3lli.fdroid.entity.UpdateCategory
|
||||
import com.machiav3lli.fdroid.ui.fragments.Request
|
||||
|
||||
@Dao
|
||||
interface ProductDao : BaseDao<Product> {
|
||||
@Query("SELECT COUNT(*) FROM product WHERE repositoryId = :id")
|
||||
fun countForRepository(id: Long): Long
|
||||
|
||||
@Query("SELECT COUNT(*) FROM product WHERE repositoryId = :id")
|
||||
fun countForRepositoryLive(id: Long): LiveData<Long>
|
||||
|
||||
@Query("SELECT * FROM product WHERE packageName = :packageName")
|
||||
fun get(packageName: String): List<Product?>
|
||||
|
||||
@Query("SELECT * FROM product WHERE packageName = :packageName")
|
||||
fun getLive(packageName: String): LiveData<List<Product?>>
|
||||
|
||||
@Query("DELETE FROM product WHERE repositoryId = :id")
|
||||
fun deleteById(id: Long): Int
|
||||
|
||||
@RawQuery
|
||||
fun queryObject(query: SupportSQLiteQuery): List<Product>
|
||||
|
||||
fun queryObject(request: Request): List<Product> = queryObject(
|
||||
buildProductQuery(
|
||||
request.installed,
|
||||
request.updates,
|
||||
request.searchQuery,
|
||||
request.section,
|
||||
request.order,
|
||||
request.numberOfItems,
|
||||
request.updateCategory
|
||||
)
|
||||
)
|
||||
|
||||
@Transaction
|
||||
fun queryObject(
|
||||
installed: Boolean, updates: Boolean, searchQuery: String,
|
||||
section: Section, order: Order, numberOfItems: Int = 0,
|
||||
updateCategory: UpdateCategory = UpdateCategory.ALL
|
||||
): List<Product> = queryObject(
|
||||
buildProductQuery(
|
||||
installed,
|
||||
updates,
|
||||
searchQuery,
|
||||
section,
|
||||
order,
|
||||
numberOfItems,
|
||||
updateCategory
|
||||
)
|
||||
)
|
||||
|
||||
@RawQuery(observedEntities = [Product::class])
|
||||
fun queryLiveList(query: SupportSQLiteQuery): LiveData<List<Product>>
|
||||
|
||||
fun queryLiveList(request: Request): LiveData<List<Product>> = queryLiveList(
|
||||
buildProductQuery(
|
||||
request.installed,
|
||||
request.updates,
|
||||
request.searchQuery,
|
||||
request.section,
|
||||
request.order,
|
||||
request.numberOfItems,
|
||||
request.updateCategory
|
||||
)
|
||||
)
|
||||
|
||||
fun buildProductQuery(
|
||||
installed: Boolean,
|
||||
updates: Boolean,
|
||||
searchQuery: String,
|
||||
section: Section,
|
||||
order: Order,
|
||||
numberOfItems: Int = 0,
|
||||
updateCategory: UpdateCategory = UpdateCategory.ALL
|
||||
): SupportSQLiteQuery {
|
||||
val builder = QueryBuilder()
|
||||
|
||||
// TODO improve signature matching logic
|
||||
val signatureMatches = """$TABLE_INSTALLED.$ROW_SIGNATURE IS NOT NULL AND
|
||||
$TABLE_PRODUCT.$ROW_SIGNATURES LIKE ('%' || $TABLE_INSTALLED.$ROW_SIGNATURE || '%') AND
|
||||
$TABLE_PRODUCT.$ROW_SIGNATURES != ''"""
|
||||
|
||||
// Select the return fields
|
||||
builder += """SELECT $TABLE_PRODUCT.rowid AS $ROW_ID, $TABLE_PRODUCT.$ROW_REPOSITORY_ID,
|
||||
$TABLE_PRODUCT.$ROW_PACKAGE_NAME, $TABLE_PRODUCT.$ROW_LABEL,
|
||||
$TABLE_PRODUCT.$ROW_SUMMARY, $TABLE_PRODUCT.$ROW_DESCRIPTION,
|
||||
(COALESCE($TABLE_EXTRAS.$ROW_IGNORED_VERSION, -1) != $TABLE_PRODUCT.$ROW_VERSION_CODE AND
|
||||
COALESCE($TABLE_EXTRAS.$ROW_IGNORE_UPDATES, 0) = 0 AND $TABLE_PRODUCT.$ROW_COMPATIBLE != 0 AND
|
||||
$TABLE_PRODUCT.$ROW_VERSION_CODE > COALESCE($TABLE_INSTALLED.$ROW_VERSION_CODE, 0xffffffff) AND
|
||||
$signatureMatches) AS $ROW_CAN_UPDATE, $TABLE_PRODUCT.$ROW_ICON,
|
||||
$TABLE_PRODUCT.$ROW_METADATA_ICON, $TABLE_PRODUCT.$ROW_RELEASES, $TABLE_PRODUCT.$ROW_CATEGORIES,
|
||||
$TABLE_PRODUCT.$ROW_ANTIFEATURES, $TABLE_PRODUCT.$ROW_LICENSES, $TABLE_PRODUCT.$ROW_DONATES,
|
||||
$TABLE_PRODUCT.$ROW_SCREENSHOTS, $TABLE_PRODUCT.$ROW_VERSION_CODE,"""
|
||||
|
||||
// Calculate the matching score with the search query
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
builder += """((($TABLE_PRODUCT.$ROW_LABEL LIKE ? OR
|
||||
$TABLE_PRODUCT.$ROW_SUMMARY LIKE ?) * 7) |
|
||||
(($TABLE_PRODUCT.$ROW_PACKAGE_NAME LIKE ?) * 3) |
|
||||
($TABLE_PRODUCT.$ROW_DESCRIPTION LIKE ?)) AS $ROW_MATCH_RANK,"""
|
||||
builder %= List(4) { "%$searchQuery%" }
|
||||
} else {
|
||||
builder += "0 AS $ROW_MATCH_RANK,"
|
||||
}
|
||||
|
||||
// Take product as main table
|
||||
builder += """MAX(($TABLE_PRODUCT.$ROW_COMPATIBLE AND
|
||||
($TABLE_INSTALLED.$ROW_SIGNATURE IS NULL OR $signatureMatches)) ||
|
||||
PRINTF('%016X', $TABLE_PRODUCT.$ROW_VERSION_CODE)) FROM $TABLE_PRODUCT_NAME AS $TABLE_PRODUCT"""
|
||||
|
||||
// Merge the matching repositories
|
||||
builder += """JOIN $TABLE_REPOSITORY_NAME AS $TABLE_REPOSITORY
|
||||
ON $TABLE_PRODUCT.$ROW_REPOSITORY_ID = $TABLE_REPOSITORY.$ROW_ID"""
|
||||
|
||||
// Merge the matching extras
|
||||
builder += """LEFT JOIN $TABLE_EXTRAS_NAME AS $TABLE_EXTRAS
|
||||
ON $TABLE_PRODUCT.$ROW_PACKAGE_NAME = $TABLE_EXTRAS.$ROW_PACKAGE_NAME"""
|
||||
|
||||
// Merge the matching installed
|
||||
if (!installed && !updates) builder += "LEFT"
|
||||
builder += """JOIN $TABLE_INSTALLED_NAME AS $TABLE_INSTALLED
|
||||
ON $TABLE_PRODUCT.$ROW_PACKAGE_NAME = $TABLE_INSTALLED.$ROW_PACKAGE_NAME"""
|
||||
|
||||
// Merge the matching category
|
||||
if (section is Section.Category) {
|
||||
builder += """JOIN $TABLE_CATEGORY_NAME AS $TABLE_CATEGORY
|
||||
ON $TABLE_PRODUCT.$ROW_PACKAGE_NAME = $TABLE_CATEGORY.$ROW_PACKAGE_NAME"""
|
||||
}
|
||||
|
||||
// Filter only active repositories
|
||||
builder += """WHERE $TABLE_REPOSITORY.$ROW_ENABLED != 0"""
|
||||
|
||||
// Filter only the selected repository/category
|
||||
if (section is Section.Category) {
|
||||
builder += "AND $TABLE_CATEGORY.$ROW_LABEL = ?"
|
||||
builder %= section.name
|
||||
} else if (section is Section.Repository) {
|
||||
builder += "AND $TABLE_PRODUCT.$ROW_REPOSITORY_ID = ?"
|
||||
builder %= section.id.toString()
|
||||
}
|
||||
|
||||
// Filter only apps that have some matching score to the search query
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
builder += """AND $ROW_MATCH_RANK > 0"""
|
||||
}
|
||||
|
||||
when (updateCategory) {
|
||||
UpdateCategory.ALL -> Unit
|
||||
UpdateCategory.NEW -> builder += """AND $TABLE_PRODUCT.$ROW_ADDED = $TABLE_PRODUCT.$ROW_UPDATED"""
|
||||
UpdateCategory.UPDATED -> builder += """AND $TABLE_PRODUCT.$ROW_ADDED < $TABLE_PRODUCT.$ROW_UPDATED"""
|
||||
}
|
||||
|
||||
// Sum up all products with the same package name
|
||||
builder += "GROUP BY $TABLE_PRODUCT.$ROW_PACKAGE_NAME HAVING 1"
|
||||
|
||||
// Filter if only can update
|
||||
if (updates) {
|
||||
builder += "AND $ROW_CAN_UPDATE"
|
||||
}
|
||||
|
||||
// Set sorting order
|
||||
builder += "ORDER BY"
|
||||
if (searchQuery.isNotEmpty()) builder += """$ROW_MATCH_RANK DESC,"""
|
||||
when (order) {
|
||||
Order.NAME -> Unit
|
||||
Order.DATE_ADDED -> builder += "$TABLE_PRODUCT.$ROW_ADDED DESC,"
|
||||
Order.LAST_UPDATE -> builder += "$TABLE_PRODUCT.$ROW_UPDATED DESC,"
|
||||
}::class
|
||||
builder += "$TABLE_PRODUCT.$ROW_LABEL COLLATE LOCALIZED ASC${if (numberOfItems > 0) " LIMIT $numberOfItems" else ""}"
|
||||
|
||||
return SimpleSQLiteQuery(builder.build(), builder.arguments.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
@Dao
|
||||
interface ProductTempDao : BaseDao<ProductTemp> {
|
||||
@get:Query("SELECT * FROM temporary_product")
|
||||
val all: Array<ProductTemp>
|
||||
|
||||
@Query("DELETE FROM temporary_product")
|
||||
fun emptyTable()
|
||||
|
||||
@Insert
|
||||
fun insertCategory(vararg product: CategoryTemp)
|
||||
|
||||
@Transaction
|
||||
fun putTemporary(products: List<Product>) {
|
||||
products.forEach {
|
||||
insert(it.asProductTemp())
|
||||
it.categories.forEach { category ->
|
||||
insertCategory(CategoryTemp().apply {
|
||||
repositoryId = it.repositoryId
|
||||
packageName = it.packageName
|
||||
label = category
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Dao
|
||||
interface ExtrasDao : BaseDao<Extras> {
|
||||
@Query("DELETE FROM extras WHERE packageName = :packageName")
|
||||
fun delete(packageName: String)
|
||||
|
||||
@Query("SELECT * FROM extras WHERE packageName = :packageName")
|
||||
operator fun get(packageName: String): Extras?
|
||||
|
||||
@Query("SELECT * FROM extras WHERE packageName = :packageName")
|
||||
fun getLive(packageName: String): LiveData<Extras?>
|
||||
|
||||
@get:Query("SELECT * FROM extras")
|
||||
val all: List<Extras>
|
||||
|
||||
@get:Query("SELECT * FROM extras")
|
||||
val allLive: LiveData<List<Extras>>
|
||||
|
||||
@get:Query("SELECT packageName FROM extras WHERE favorite != 0")
|
||||
val favorites: Array<String>
|
||||
|
||||
@get:Query("SELECT packageName FROM extras WHERE favorite != 0")
|
||||
val favoritesLive: LiveData<Array<String>>
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.machiav3lli.fdroid.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.machiav3lli.fdroid.database.entity.Release
|
||||
|
||||
@Dao
|
||||
interface ReleaseDao : BaseDao<Release> {
|
||||
// This one for the mode combining releases of different sources
|
||||
@Query("SELECT * FROM `release` WHERE packageName = :packageName")
|
||||
fun get(packageName: String): List<Release?>
|
||||
|
||||
// This one for the separating releases of different sources
|
||||
@Query("SELECT * FROM `release` WHERE packageName = :packageName AND signature = :signature")
|
||||
fun get(packageName: String, signature: String): List<Release?>
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.machiav3lli.fdroid.database.dao
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import com.machiav3lli.fdroid.database.entity.Repository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface RepositoryDao : BaseDao<Repository> {
|
||||
@get:Query("SELECT COUNT(_id) FROM repository")
|
||||
val count: Int
|
||||
|
||||
fun put(repository: Repository): Repository {
|
||||
repository.let { item ->
|
||||
val newId = if (item.id > 0L) update(item).toLong() else returnInsert(item)
|
||||
return if (newId != repository.id) repository.copy(id = newId) else repository
|
||||
}
|
||||
}
|
||||
|
||||
@Insert
|
||||
fun returnInsert(product: Repository): Long
|
||||
|
||||
@Query("SELECT * FROM repository WHERE _id = :id")
|
||||
fun get(id: Long): Repository?
|
||||
|
||||
@Query("SELECT * FROM repository WHERE _id = :id")
|
||||
fun getLive(id: Long): LiveData<Repository?>
|
||||
|
||||
@Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||
fun getAllRepositories(): Flow<List<Repository>>
|
||||
|
||||
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||
val all: List<Repository>
|
||||
|
||||
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||
val allLive: LiveData<List<Repository>>
|
||||
|
||||
@get:Query("SELECT _id FROM repository WHERE enabled == 0 ORDER BY _id ASC")
|
||||
val allDisabled: List<Long>
|
||||
|
||||
// TODO clean up products and other tables afterwards
|
||||
@Query("DELETE FROM repository WHERE _id = :id")
|
||||
fun deleteById(id: Long)
|
||||
|
||||
@Query("SELECT MAX(_id) FROM repository")
|
||||
fun latestAddedId(): Long
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.machiav3lli.fdroid.database.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import com.machiav3lli.fdroid.*
|
||||
|
||||
@Entity(
|
||||
tableName = TABLE_CATEGORY_NAME,
|
||||
primaryKeys = [ROW_REPOSITORY_ID, ROW_PACKAGE_NAME, ROW_LABEL]
|
||||
)
|
||||
open class Category {
|
||||
var repositoryId: Long = 0
|
||||
var packageName = ""
|
||||
var label = ""
|
||||
}
|
||||
|
||||
@Entity(tableName = TABLE_CATEGORY_TEMP_NAME)
|
||||
class CategoryTemp : Category()
|
@ -0,0 +1,14 @@
|
||||
package com.machiav3lli.fdroid.database.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.machiav3lli.fdroid.TABLE_EXTRAS_NAME
|
||||
|
||||
@Entity(tableName = TABLE_EXTRAS_NAME)
|
||||
data class Extras(
|
||||
@PrimaryKey
|
||||
var packageName: String = "",
|
||||
var favorite: Boolean = false,
|
||||
var ignoreUpdates: Boolean = false,
|
||||
var ignoredVersion: Long = 0L,
|
||||
)
|
@ -0,0 +1,16 @@
|
||||
package com.machiav3lli.fdroid.database.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.machiav3lli.fdroid.TABLE_INSTALLED_NAME
|
||||
|
||||
@Entity(tableName = TABLE_INSTALLED_NAME)
|
||||
data class Installed(
|
||||
@PrimaryKey
|
||||
var packageName: String = "",
|
||||
var version: String = "",
|
||||
var versionCode: Long = 0L,
|
||||
var signature: String = "",
|
||||
var isSystem: Boolean = false,
|
||||
val launcherActivities: List<Pair<String, String>> = emptyList()
|
||||
)
|
@ -0,0 +1,210 @@
|
||||
package com.machiav3lli.fdroid.database.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import com.machiav3lli.fdroid.ROW_PACKAGE_NAME
|
||||
import com.machiav3lli.fdroid.ROW_REPOSITORY_ID
|
||||
import com.machiav3lli.fdroid.TABLE_PRODUCT_NAME
|
||||
import com.machiav3lli.fdroid.TABLE_PRODUCT_TEMP_NAME
|
||||
import com.machiav3lli.fdroid.entity.Author
|
||||
import com.machiav3lli.fdroid.entity.Donate
|
||||
import com.machiav3lli.fdroid.entity.ProductItem
|
||||
import com.machiav3lli.fdroid.entity.Screenshot
|
||||
import com.machiav3lli.fdroid.utility.extension.text.nullIfEmpty
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
// TODO Add Product Extras to handle favorite lists etc..
|
||||
@Entity(tableName = TABLE_PRODUCT_NAME, primaryKeys = [ROW_REPOSITORY_ID, ROW_PACKAGE_NAME])
|
||||
@Serializable
|
||||
open class Product(
|
||||
var repositoryId: Long,
|
||||
var packageName: String
|
||||
) {
|
||||
var label: String = ""
|
||||
var summary: String = ""
|
||||
var description: String = ""
|
||||
var added: Long = 0L
|
||||
var updated: Long = 0L
|
||||
var icon: String = ""
|
||||
var metadataIcon: String = ""
|
||||
var releases: List<Release> = emptyList()
|
||||
var categories: List<String> = emptyList()
|
||||
var antiFeatures: List<String> = emptyList()
|
||||
var licenses: List<String> = emptyList()
|
||||
var donates: List<Donate> = emptyList()
|
||||
var screenshots: List<Screenshot> = emptyList()
|
||||
var versionCode: Long = 0L
|
||||
var suggestedVersionCode: Long = 0L
|
||||
var signatures: List<String> = emptyList()
|
||||
var compatible: Boolean = false
|
||||
var author: Author = Author()
|
||||
var source: String = ""
|
||||
var web: String = ""
|
||||
var tracker: String = ""
|
||||
var changelog: String = ""
|
||||
var whatsNew: String = ""
|
||||
|
||||
constructor(
|
||||
repositoryId: Long,
|
||||
packageName: String,
|
||||
label: String,
|
||||
summary: String,
|
||||
description: String,
|
||||
added: Long,
|
||||
updated: Long,
|
||||
icon: String,
|
||||
metadataIcon: String,
|
||||
releases: List<Release>,
|
||||
categories: List<String>,
|
||||
antiFeatures: List<String>,
|
||||
licenses: List<String>,
|
||||
donates: List<Donate>,
|
||||
screenshots: List<Screenshot>,
|
||||
suggestedVersionCode: Long = 0L,
|
||||
author: Author = Author(),
|
||||
source: String = "",
|
||||
web: String = "",
|
||||
tracker: String = "",
|
||||
changelog: String = "",
|
||||
whatsNew: String = ""
|
||||
) : this(repositoryId, packageName) {
|
||||
this.label = label
|
||||
this.summary = summary
|
||||
this.description = description
|
||||
this.added = added
|
||||
this.updated = updated
|
||||
this.icon = icon
|
||||
this.metadataIcon = metadataIcon
|
||||
this.releases = releases
|
||||
this.categories = categories
|
||||
this.antiFeatures = antiFeatures
|
||||
this.licenses = licenses
|
||||
this.donates = donates
|
||||
this.screenshots = screenshots
|
||||
this.versionCode = selectedReleases.firstOrNull()?.versionCode ?: 0L
|
||||
this.suggestedVersionCode = suggestedVersionCode
|
||||
this.signatures = selectedReleases.mapNotNull { it.signature.nullIfEmpty() }.distinct()
|
||||
this.compatible = selectedReleases.firstOrNull()?.incompatibilities?.isEmpty() == true
|
||||
this.author = author
|
||||
this.source = source
|
||||
this.web = web
|
||||
this.tracker = tracker
|
||||
this.changelog = changelog
|
||||
this.whatsNew = whatsNew
|
||||
}
|
||||
|
||||
val selectedReleases: List<Release>
|
||||
get() = releases.filter { it.selected }
|
||||
|
||||
val displayRelease: Release?
|
||||
get() = selectedReleases.firstOrNull() ?: releases.firstOrNull()
|
||||
|
||||
val version: String
|
||||
get() = displayRelease?.version.orEmpty()
|
||||
|
||||
fun toItem(installed: Installed? = null): ProductItem =
|
||||
ProductItem(
|
||||
repositoryId,
|
||||
packageName,
|
||||
label,
|
||||
summary,
|
||||
icon,
|
||||
metadataIcon,
|
||||
version,
|
||||
"",
|
||||
compatible,
|
||||
canUpdate(installed),
|
||||
0
|
||||
)
|
||||
|
||||
fun canUpdate(installed: Installed?): Boolean =
|
||||
installed != null && compatible && versionCode > installed.versionCode && installed.signature in signatures
|
||||
|
||||
fun refreshVariables() {
|
||||
this.versionCode = selectedReleases.firstOrNull()?.versionCode ?: 0L
|
||||
this.signatures = selectedReleases.mapNotNull { it.signature.nullIfEmpty() }.distinct()
|
||||
this.compatible = selectedReleases.firstOrNull()?.incompatibilities?.isEmpty() == true
|
||||
}
|
||||
|
||||
fun toJSON() = Json.encodeToString(this)
|
||||
|
||||
companion object {
|
||||
fun fromJson(json: String) = Json.decodeFromString<Product>(json)
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(tableName = TABLE_PRODUCT_TEMP_NAME)
|
||||
class ProductTemp(
|
||||
repositoryId: Long,
|
||||
packageName: String,
|
||||
label: String,
|
||||
summary: String,
|
||||
description: String,
|
||||
added: Long,
|
||||
updated: Long,
|
||||
icon: String,
|
||||
metadataIcon: String,
|
||||
releases: List<Release>,
|
||||
categories: List<String>,
|
||||
antiFeatures: List<String>,
|
||||
licenses: List<String>,
|
||||
donates: List<Donate>,
|
||||
screenshots: List<Screenshot>,
|
||||
suggestedVersionCode: Long = 0L,
|
||||
author: Author = Author(),
|
||||
source: String = "",
|
||||
web: String = "",
|
||||
tracker: String = "",
|
||||
changelog: String = "",
|
||||
whatsNew: String = ""
|
||||
) : Product(
|
||||
repositoryId = repositoryId,
|
||||
packageName = packageName,
|
||||
label = label,
|
||||
summary = summary,
|
||||
description = description,
|
||||
added = added,
|
||||
updated = updated,
|
||||
icon = icon,
|
||||
metadataIcon = metadataIcon,
|
||||
releases = releases,
|
||||
categories = categories,
|
||||
antiFeatures = antiFeatures,
|
||||
licenses = licenses,
|
||||
donates = donates,
|
||||
screenshots = screenshots,
|
||||
suggestedVersionCode = suggestedVersionCode,
|
||||
author = author,
|
||||
source = source,
|
||||
web = web,
|
||||
tracker = tracker,
|
||||
changelog = changelog,
|
||||
whatsNew = whatsNew
|
||||
)
|
||||
|
||||
fun Product.asProductTemp(): ProductTemp = ProductTemp(
|
||||
repositoryId = repositoryId,
|
||||
packageName = packageName,
|
||||
label = label,
|
||||
summary = summary,
|
||||
description = description,
|
||||
added = added,
|
||||
updated = updated,
|
||||
icon = icon,
|
||||
metadataIcon = metadataIcon,
|
||||
releases = releases,
|
||||
categories = categories,
|
||||
antiFeatures = antiFeatures,
|
||||
licenses = licenses,
|
||||
donates = donates,
|
||||
screenshots = screenshots,
|
||||
suggestedVersionCode = suggestedVersionCode,
|
||||
author = author,
|
||||
source = source,
|
||||
web = web,
|
||||
tracker = tracker,
|
||||
changelog = changelog,
|
||||
whatsNew = whatsNew
|
||||
)
|
@ -0,0 +1,82 @@
|
||||
package com.machiav3lli.fdroid.database.entity
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.room.Entity
|
||||
import com.machiav3lli.fdroid.ROW_PACKAGE_NAME
|
||||
import com.machiav3lli.fdroid.ROW_SIGNATURE
|
||||
import com.machiav3lli.fdroid.ROW_VERSION_CODE
|
||||
import com.machiav3lli.fdroid.TABLE_RELEASE_NAME
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
// TODO make a Room entity
|
||||
@Entity(
|
||||
tableName = TABLE_RELEASE_NAME,
|
||||
primaryKeys = [ROW_PACKAGE_NAME, ROW_VERSION_CODE, ROW_SIGNATURE]
|
||||
)
|
||||
@Serializable
|
||||
data class Release(
|
||||
val packageName: String,
|
||||
val selected: Boolean,
|
||||
val version: String,
|
||||
val versionCode: Long,
|
||||
val added: Long,
|
||||
val size: Long,
|
||||
val minSdkVersion: Int,
|
||||
val targetSdkVersion: Int,
|
||||
val maxSdkVersion: Int,
|
||||
val source: String,
|
||||
val release: String,
|
||||
val hash: String,
|
||||
val hashType: String,
|
||||
val signature: String,
|
||||
val obbMain: String,
|
||||
val obbMainHash: String,
|
||||
val obbMainHashType: String,
|
||||
val obbPatch: String,
|
||||
val obbPatchHash: String,
|
||||
val obbPatchHashType: String,
|
||||
val permissions: List<String>,
|
||||
val features: List<String>,
|
||||
val platforms: List<String>,
|
||||
val incompatibilities: List<Incompatibility>,
|
||||
) {
|
||||
@Serializable
|
||||
sealed class Incompatibility {
|
||||
@Serializable
|
||||
object MinSdk : Incompatibility()
|
||||
|
||||
@Serializable
|
||||
object MaxSdk : Incompatibility()
|
||||
|
||||
@Serializable
|
||||
object Platform : Incompatibility()
|
||||
|
||||
@Serializable
|
||||
data class Feature(val feature: String) : Incompatibility()
|
||||
|
||||
fun toJSON() = Json.encodeToString(this)
|
||||
|
||||
companion object {
|
||||
fun fromJson(json: String) = Json.decodeFromString<Incompatibility>(json)
|
||||
}
|
||||
}
|
||||
|
||||
val identifier: String
|
||||
get() = "$versionCode.$hash"
|
||||
|
||||
fun getDownloadUrl(repository: Repository): String {
|
||||
return Uri.parse(repository.address).buildUpon().appendPath(release).build().toString()
|
||||
}
|
||||
|
||||
val cacheFileName: String
|
||||
get() = "${hash.replace('/', '-')}.apk"
|
||||
|
||||
fun toJSON() = Json.encodeToString(this)
|
||||
|
||||
companion object {
|
||||
fun fromJson(json: String) = Json.decodeFromString<Release>(json)
|
||||
}
|
||||
}
|
@ -0,0 +1,289 @@
|
||||
package com.machiav3lli.fdroid.database.entity
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.machiav3lli.fdroid.ROW_ID
|
||||
import com.machiav3lli.fdroid.TABLE_REPOSITORY_NAME
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.net.URL
|
||||
|
||||
@Entity(tableName = TABLE_REPOSITORY_NAME)
|
||||
@Serializable
|
||||
data class Repository(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = ROW_ID)
|
||||
var id: Long = 0,
|
||||
var address: String = "",
|
||||
var mirrors: List<String> = emptyList(),
|
||||
var name: String = "",
|
||||
var description: String = "",
|
||||
var version: Int = 21,
|
||||
var enabled: Boolean = false,
|
||||
var fingerprint: String = "",
|
||||
var lastModified: String = "",
|
||||
var entityTag: String = "",
|
||||
var updated: Long = 0L,
|
||||
var timestamp: Long = 0L,
|
||||
var authentication: String = "",
|
||||
) {
|
||||
fun edit(address: String, fingerprint: String, authentication: String): Repository = apply {
|
||||
val changed = this.address != address || this.fingerprint != fingerprint
|
||||
this.lastModified = if (changed) "" else lastModified
|
||||
this.entityTag = if (changed) "" else entityTag
|
||||
this.address = address
|
||||
this.fingerprint = fingerprint
|
||||
this.authentication = authentication
|
||||
}
|
||||
|
||||
fun update(
|
||||
mirrors: List<String>, name: String, description: String, version: Int,
|
||||
lastModified: String, entityTag: String, timestamp: Long,
|
||||
): Repository = apply {
|
||||
this.mirrors = mirrors
|
||||
this.name = name
|
||||
this.description = description
|
||||
this.version = if (version >= 0) version else this.version
|
||||
this.lastModified = lastModified
|
||||
this.entityTag = entityTag
|
||||
this.updated = System.currentTimeMillis()
|
||||
this.timestamp = timestamp
|
||||
}
|
||||
|
||||
fun enable(enabled: Boolean): Repository = apply {
|
||||
this.enabled = enabled
|
||||
this.lastModified = ""
|
||||
this.entityTag = ""
|
||||
}
|
||||
|
||||
fun toJSON() = Json.encodeToString(this)
|
||||
|
||||
companion object {
|
||||
fun fromJson(json: String) = Json.decodeFromString<Repository>(json)
|
||||
|
||||
fun newRepository(
|
||||
address: String = "",
|
||||
fingerprint: String = "",
|
||||
authentication: String = "",
|
||||
): Repository {
|
||||
val name = try {
|
||||
URL(address).let { "${it.host}${it.path}" }
|
||||
} catch (e: Exception) {
|
||||
address
|
||||
}
|
||||
return Repository(
|
||||
address = address,
|
||||
name = name,
|
||||
fingerprint = fingerprint,
|
||||
authentication = authentication
|
||||
)
|
||||
}
|
||||
|
||||
private fun defaultRepository(
|
||||
address: String, name: String, description: String,
|
||||
version: Int, enabled: Boolean, fingerprint: String, authentication: String,
|
||||
): Repository = Repository(
|
||||
0, address, emptyList(), name, description, version, enabled,
|
||||
fingerprint, "", "", 0L, 0L, authentication
|
||||
)
|
||||
|
||||
val defaultRepositories = listOf(run {
|
||||
defaultRepository(
|
||||
"https://f-droid.org/repo",
|
||||
"F-Droid",
|
||||
"The official F-Droid Free Software repository. " +
|
||||
"Everything in this repository is always built from the source code.",
|
||||
21,
|
||||
true,
|
||||
"43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB",
|
||||
""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://f-droid.org/archive",
|
||||
"F-Droid Archive",
|
||||
"The archive of the official F-Droid Free " +
|
||||
"Software repository. Apps here are old and can contain known vulnerabilities and security issues!",
|
||||
21,
|
||||
false,
|
||||
"43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB",
|
||||
""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://guardianproject.info/fdroid/repo",
|
||||
"Guardian Project Official Releases",
|
||||
"The " +
|
||||
"official repository of The Guardian Project apps for use with the F-Droid client. Applications in this " +
|
||||
"repository are official binaries built by the original application developers and signed by the same key as " +
|
||||
"the APKs that are released in the Google Play Store.",
|
||||
21,
|
||||
false,
|
||||
"B7C2EEFD8DAC7806AF67DFCD92EB18126BC08312A7F2D6F3862E46013C7A6135",
|
||||
""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://guardianproject.info/fdroid/archive",
|
||||
"Guardian Project Archive",
|
||||
"The official " +
|
||||
"repository of The Guardian Project apps for use with the F-Droid client. This contains older versions of " +
|
||||
"applications from the main repository.",
|
||||
21,
|
||||
false,
|
||||
"B7C2EEFD8DAC7806AF67DFCD92EB18126BC08312A7F2D6F3862E46013C7A6135",
|
||||
""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://apt.izzysoft.de/fdroid/repo", "IzzyOnDroid F-Droid Repo", "This is a " +
|
||||
"repository of apps to be used with F-Droid the original application developers, taken from the resp. " +
|
||||
"repositories (mostly GitHub). At this moment I cannot give guarantees on regular updates for all of them, " +
|
||||
"though most are checked multiple times a week ", 21, true,
|
||||
"3BF0D6ABFEAE2F401707B6D966BE743BF0EEE49C2561B9BA39073711F628937A", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://microg.org/fdroid/repo", "MicroG Project",
|
||||
"Official repository of the open-source implementation of Google Play Services.",
|
||||
21, false, "9BD06727E62796C0130EB6DAB39B73157451582CBD138E86C468ACC395D14165", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://repo.netsyms.com/fdroid/repo", "Netsyms Technologies",
|
||||
"Open-source apps created by Netsyms Technologies.",
|
||||
21, false, "2581BA7B32D3AB443180C4087CAB6A7E8FB258D3A6E98870ECB3C675E4D64489", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://fdroid.bromite.org/fdroid/repo", "Bromite",
|
||||
"Bromite is a Chromium plus ad blocking and enhanced privacy; take back your browser.",
|
||||
21, false, "E1EE5CD076D7B0DC84CB2B45FB78B86DF2EB39A3B6C56BA3DC292A5E0C3B9504", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://molly.im/fdroid/foss/fdroid/repo", "Molly",
|
||||
"Molly is a fork of Signal focused on security.",
|
||||
21, false, "5198DAEF37FC23C14D5EE32305B2AF45787BD7DF2034DE33AD302BDB3446DF74", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://archive.newpipe.net/fdroid/repo", "NewPipe",
|
||||
"NewPipe's official independent repository.",
|
||||
21, false, "E2402C78F9B97C6C89E97DB914A2751FDA1D02FE2039CC0897A462BDB57E7501", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://www.collaboraoffice.com/downloads/fdroid/repo", "Collabora Office",
|
||||
"Collabora Office is an office suite based on LibreOffice.",
|
||||
21, false, "573258C84E149B5F4D9299E7434B2B69A8410372921D4AE586BA91EC767892CC", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://www.droidware.info/fdroid/repo", "Ungoogled Chromium",
|
||||
"Chromium sans dependency on Google web services. It also features some enhancments to privacy, control & transparency",
|
||||
21, false, "2144449AB1DD270EC31B6087409B5D0EA39A75A9F290DA62AC1B238A0EAAF851", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://fdroid.libretro.com/repo", "LibRetro",
|
||||
"The official canary repository for this great retro emulators hub.",
|
||||
21, false, "3F05B24D497515F31FEAB421297C79B19552C5C81186B3750B7C131EF41D733D", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://cdn.kde.org/android/fdroid/repo", "KDE Android",
|
||||
"The official nightly repository for KDE Android apps.",
|
||||
21, false, "B3EBE10AFA6C5C400379B34473E843D686C61AE6AD33F423C98AF903F056523F", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://rfc2822.gitlab.io/fdroid-firefox/fdroid/repo", "Unofficial Firefox",
|
||||
"An unofficial repository with some of the most well known FOSS apps not on F-Droid.",
|
||||
21, false, "8F992BBBA0340EFE6299C7A410B36D9C8889114CA6C58013C3587CDA411B4AED", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://calyxos.gitlab.io/calyx-fdroid-repo/fdroid/repo", "Calyx OS Repo",
|
||||
"The official Calyx Labs F-Droid repository.",
|
||||
21, false, "C44D58B4547DE5096138CB0B34A1CC99DAB3B4274412ED753FCCBFC11DC1B7B6", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://divestos.org/fdroid/official", "Divest OS Repo",
|
||||
"The official Divest OS F-Droid repository.",
|
||||
21, false, "E4BE8D6ABFA4D9D4FEEF03CDDA7FF62A73FD64B75566F6DD4E5E577550BE8467", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://fdroid.fedilab.app/repo", "Fedilab",
|
||||
"Fedilab's official F-Droid repository.",
|
||||
21, false, "11F0A69910A4280E2CD3CCC3146337D006BE539B18E1A9FEACE15FF757A94FEB", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://store.nethunter.com/repo", "Kali Nethunter",
|
||||
"Kali Nethunter's official selection of original binaries.",
|
||||
21, false, "7E418D34C3AD4F3C37D7E6B0FACE13332364459C862134EB099A3BDA2CCF4494", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://secfirst.org/fdroid/repo", "Umbrella",
|
||||
"Security advices, tutorials, tools etc..",
|
||||
21, false, "39EB57052F8D684514176819D1645F6A0A7BD943DBC31AB101949006AC0BC228", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://thecapslock.gitlab.io/fdroid-patched-apps/fdroid/repo", "Patched Apps",
|
||||
"A collection of patched applications to provide better compatibility, privacy etc..",
|
||||
21, false, "313D9E6E789FF4E8E2D687AAE31EEF576050003ED67963301821AC6D3763E3AC", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://mobileapp.bitwarden.com/fdroid/repo", "Bitwarden",
|
||||
"The official repository for Bitwarden.",
|
||||
21, false, "BC54EA6FD1CD5175BCCCC47C561C5726E1C3ED7E686B6DB4B18BAC843A3EFE6C", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://briarproject.org/fdroid/repo", "Briar",
|
||||
"An serverless/offline messenger that hides your metadata.",
|
||||
21, false, "1FB874BEE7276D28ECB2C9B06E8A122EC4BCB4008161436CE474C257CBF49BD6", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://guardianproject-wind.s3.amazonaws.com/fdroid/repo", "Wind Project",
|
||||
"A collection of interesting offline/serverless apps.",
|
||||
21, false, "182CF464D219D340DA443C62155198E399FEC1BC4379309B775DD9FC97ED97E1", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://repo.alefvanoon.xyz/fdroid/repo", "Alefvanoon",
|
||||
"A collection of open-source apps that for one reason or another not on F-Droid.",
|
||||
21, false, "04DF198F553069C7BE60F057AE12000E99F7700DA895CC1CE2EB11DC871581F1", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://repo.unifiedpush.org/", "UnifiedPush",
|
||||
"A repository of apps for unifiedPush.",
|
||||
21, false, "DF11176406C63A7876103CE6CC1A8FCA239DF76AA5F6DE5CDBAFE73ECDBF1875", ""
|
||||
)
|
||||
}, run {
|
||||
defaultRepository(
|
||||
"https://nanolx.org/fdroid/repo", "NanoDroid",
|
||||
"A companion repository to microG's installer.",
|
||||
21, false, "862ED9F13A3981432BF86FE93D14596B381D75BE83A1D616E2D44A12654AD015", ""
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
class IdAndDeleted {
|
||||
@ColumnInfo(name = "_id")
|
||||
var id = 0L
|
||||
|
||||
var deleted = false
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user