mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-24 03:42:15 +00:00
Update: Merge Repository's entity and database.entity classes
+ Update related DAOs + Add needed converters + Fix calls
This commit is contained in:
parent
050ecfd4a0
commit
7bbac86dd4
@ -214,7 +214,7 @@ class MainApplication : Application(), ImageLoaderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun forceSyncAll() {
|
private fun forceSyncAll() {
|
||||||
db.repositoryDao.all.mapNotNull { it.trueData }.forEach {
|
db.repositoryDao.all.forEach {
|
||||||
if (it.lastModified.isNotEmpty() || it.entityTag.isNotEmpty()) {
|
if (it.lastModified.isNotEmpty() || it.entityTag.isNotEmpty()) {
|
||||||
db.repositoryDao.put(it.copy(lastModified = "", entityTag = ""))
|
db.repositoryDao.put(it.copy(lastModified = "", entityTag = ""))
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,21 @@ package com.looker.droidify.database
|
|||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.utility.jsonGenerate
|
import com.looker.droidify.utility.jsonGenerate
|
||||||
import com.looker.droidify.utility.jsonParse
|
import com.looker.droidify.utility.jsonParse
|
||||||
|
|
||||||
object Converters {
|
object Converters {
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun toRepository(byteArray: ByteArray) = byteArray.jsonParse { Repository.deserialize(it) }
|
fun toStringList(byteArray: ByteArray): List<String> {
|
||||||
|
val string = byteArray.toString()
|
||||||
|
return if (string == "") emptyList()
|
||||||
|
else string.split(",")
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun toByteArray(repository: Repository) = jsonGenerate(repository::serialize)
|
fun toString(list: List<String>): ByteArray = list.toString().toByteArray()
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -32,15 +32,9 @@ interface RepositoryDao : BaseDao<Repository> {
|
|||||||
@get:Query("SELECT COUNT(_id) FROM repository")
|
@get:Query("SELECT COUNT(_id) FROM repository")
|
||||||
val count: Int
|
val count: Int
|
||||||
|
|
||||||
fun put(repository: com.looker.droidify.entity.Repository): com.looker.droidify.entity.Repository {
|
fun put(repository: Repository): Repository {
|
||||||
repository.let {
|
repository.let { item ->
|
||||||
val dbRepo = Repository().apply {
|
val newId = if (item.id > 0L) update(item).toLong() else returnInsert(item)
|
||||||
if (it.id >= 0L) id = it.id
|
|
||||||
enabled = if (it.enabled) 1 else 0
|
|
||||||
deleted = false
|
|
||||||
data = it
|
|
||||||
}
|
|
||||||
val newId = if (it.id > 0L) update(dbRepo).toLong() else returnInsert(dbRepo)
|
|
||||||
return if (newId != repository.id) repository.copy(id = newId) else repository
|
return if (newId != repository.id) repository.copy(id = newId) else repository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,35 +42,30 @@ interface RepositoryDao : BaseDao<Repository> {
|
|||||||
@Insert
|
@Insert
|
||||||
fun returnInsert(product: Repository): Long
|
fun returnInsert(product: Repository): Long
|
||||||
|
|
||||||
@Query("SELECT * FROM repository WHERE _id = :id and deleted == 0")
|
@Query("SELECT * FROM repository WHERE _id = :id")
|
||||||
fun get(id: Long): Repository?
|
fun get(id: Long): Repository?
|
||||||
|
|
||||||
@Query("SELECT * FROM repository WHERE _id = :id and deleted == 0")
|
@Query("SELECT * FROM repository WHERE _id = :id")
|
||||||
fun getLive(id: Long): LiveData<Repository?>
|
fun getLive(id: Long): LiveData<Repository?>
|
||||||
|
|
||||||
@get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC")
|
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||||
val allCursor: Cursor
|
val allCursor: Cursor
|
||||||
|
|
||||||
@get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC")
|
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||||
val all: List<Repository>
|
val all: List<Repository>
|
||||||
|
|
||||||
@get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC")
|
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||||
val allLive: LiveData<List<Repository>>
|
val allLive: LiveData<List<Repository>>
|
||||||
|
|
||||||
@get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC")
|
@get:Query("SELECT * FROM repository ORDER BY _id ASC")
|
||||||
val allFlowable: Flowable<List<Repository>>
|
val allFlowable: Flowable<List<Repository>>
|
||||||
|
|
||||||
@get:Query("SELECT _id, deleted FROM repository WHERE deleted != 0 and enabled == 0 ORDER BY _id ASC")
|
@get:Query("SELECT _id FROM repository WHERE enabled == 0 ORDER BY _id ASC")
|
||||||
val allDisabledDeleted: List<Repository.IdAndDeleted>
|
val allDisabled: List<Long>
|
||||||
|
|
||||||
|
// TODO clean up products and other tables afterwards
|
||||||
@Query("DELETE FROM repository WHERE _id = :id")
|
@Query("DELETE FROM repository WHERE _id = :id")
|
||||||
fun deleteById(id: Long): Int
|
fun deleteById(id: Long): Int
|
||||||
|
|
||||||
// TODO optimize
|
|
||||||
@Update(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun markAsDeleted(id: Long) {
|
|
||||||
get(id).apply { this?.deleted = true }?.let { update(it) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@ -148,8 +137,7 @@ interface ProductDao : BaseDao<Product> {
|
|||||||
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
|
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
|
||||||
}
|
}
|
||||||
|
|
||||||
builder += """WHERE repository.${ROW_ENABLED} != 0 AND
|
builder += """WHERE repository.${ROW_ENABLED} != 0"""
|
||||||
repository.${ROW_DELETED} == 0"""
|
|
||||||
|
|
||||||
if (section is ProductItem.Section.Category) {
|
if (section is ProductItem.Section.Category) {
|
||||||
builder += "AND category.${ROW_NAME} = ?"
|
builder += "AND category.${ROW_NAME} = ?"
|
||||||
@ -238,8 +226,7 @@ interface ProductDao : BaseDao<Product> {
|
|||||||
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
|
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
|
||||||
}
|
}
|
||||||
|
|
||||||
builder += """WHERE repository.${ROW_ENABLED} != 0 AND
|
builder += """WHERE repository.${ROW_ENABLED} != 0"""
|
||||||
repository.${ROW_DELETED} == 0"""
|
|
||||||
|
|
||||||
if (section is ProductItem.Section.Category) {
|
if (section is ProductItem.Section.Category) {
|
||||||
builder += "AND category.${ROW_NAME} = ?"
|
builder += "AND category.${ROW_NAME} = ?"
|
||||||
@ -282,8 +269,7 @@ interface CategoryDao : BaseDao<Category> {
|
|||||||
FROM category AS category
|
FROM category AS category
|
||||||
JOIN repository AS repository
|
JOIN repository AS repository
|
||||||
ON category.repository_id = repository._id
|
ON category.repository_id = repository._id
|
||||||
WHERE repository.enabled != 0 AND
|
WHERE repository.enabled != 0"""
|
||||||
repository.deleted == 0"""
|
|
||||||
)
|
)
|
||||||
val allNames: List<String>
|
val allNames: List<String>
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import androidx.room.Room
|
|||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
import com.looker.droidify.database.entity.*
|
import com.looker.droidify.database.entity.*
|
||||||
import com.looker.droidify.entity.Repository.Companion.defaultRepositories
|
import com.looker.droidify.database.entity.Repository.Companion.defaultRepositories
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -77,7 +77,7 @@ abstract class DatabaseX : RoomDatabase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun finishTemporary(repository: com.looker.droidify.entity.Repository, success: Boolean) {
|
fun finishTemporary(repository: Repository, success: Boolean) {
|
||||||
runInTransaction {
|
runInTransaction {
|
||||||
if (success) {
|
if (success) {
|
||||||
productDao.deleteById(repository.id)
|
productDao.deleteById(repository.id)
|
||||||
|
@ -3,23 +3,331 @@ package com.looker.droidify.database.entity
|
|||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import com.looker.droidify.entity.Repository
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.looker.droidify.utility.extension.json.collectNotNullStrings
|
||||||
|
import com.looker.droidify.utility.extension.json.forEachKey
|
||||||
|
import com.looker.droidify.utility.extension.json.writeArray
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
// TODO LATER: reduce redundancy by merging the entity and database classes
|
|
||||||
@Entity
|
@Entity
|
||||||
class Repository {
|
data class Repository(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
@ColumnInfo(name = "_id")
|
@ColumnInfo(name = "_id")
|
||||||
var id: Long = 0
|
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
|
||||||
|
}
|
||||||
|
|
||||||
var enabled = 0
|
fun update(
|
||||||
var deleted = false
|
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
|
||||||
|
}
|
||||||
|
|
||||||
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
|
fun enable(enabled: Boolean): Repository = apply {
|
||||||
var data: Repository? = null
|
this.enabled = enabled
|
||||||
|
this.lastModified = ""
|
||||||
|
this.entityTag = ""
|
||||||
|
}
|
||||||
|
|
||||||
val trueData: Repository?
|
fun serialize(generator: JsonGenerator) {
|
||||||
get() = data?.copy(id = id)
|
generator.writeNumberField("serialVersion", 1)
|
||||||
|
generator.writeNumberField("id", id)
|
||||||
|
generator.writeStringField("address", address)
|
||||||
|
generator.writeArray("mirrors") { mirrors.forEach { writeString(it) } }
|
||||||
|
generator.writeStringField("name", name)
|
||||||
|
generator.writeStringField("description", description)
|
||||||
|
generator.writeNumberField("version", version)
|
||||||
|
generator.writeBooleanField("enabled", enabled)
|
||||||
|
generator.writeStringField("fingerprint", fingerprint)
|
||||||
|
generator.writeStringField("lastModified", lastModified)
|
||||||
|
generator.writeStringField("entityTag", entityTag)
|
||||||
|
generator.writeNumberField("updated", updated)
|
||||||
|
generator.writeNumberField("timestamp", timestamp)
|
||||||
|
generator.writeStringField("authentication", authentication)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun deserialize(parser: JsonParser): Repository {
|
||||||
|
var id = 0L
|
||||||
|
var address = ""
|
||||||
|
var mirrors = emptyList<String>()
|
||||||
|
var name = ""
|
||||||
|
var description = ""
|
||||||
|
var version = 0
|
||||||
|
var enabled = false
|
||||||
|
var fingerprint = ""
|
||||||
|
var lastModified = ""
|
||||||
|
var entityTag = ""
|
||||||
|
var updated = 0L
|
||||||
|
var timestamp = 0L
|
||||||
|
var authentication = ""
|
||||||
|
parser.forEachKey {
|
||||||
|
when {
|
||||||
|
it.string("id") -> id = valueAsLong
|
||||||
|
it.string("address") -> address = valueAsString
|
||||||
|
it.array("mirrors") -> mirrors = collectNotNullStrings()
|
||||||
|
it.string("name") -> name = valueAsString
|
||||||
|
it.string("description") -> description = valueAsString
|
||||||
|
it.number("version") -> version = valueAsInt
|
||||||
|
it.boolean("enabled") -> enabled = valueAsBoolean
|
||||||
|
it.string("fingerprint") -> fingerprint = valueAsString
|
||||||
|
it.string("lastModified") -> lastModified = valueAsString
|
||||||
|
it.string("entityTag") -> entityTag = valueAsString
|
||||||
|
it.number("updated") -> updated = valueAsLong
|
||||||
|
it.number("timestamp") -> timestamp = valueAsLong
|
||||||
|
it.string("authentication") -> authentication = valueAsString
|
||||||
|
else -> skipChildren()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Repository(
|
||||||
|
id, address, mirrors, name, description, version, enabled, fingerprint,
|
||||||
|
lastModified, entityTag, updated, timestamp, authentication
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
class IdAndDeleted {
|
||||||
@ColumnInfo(name = "_id")
|
@ColumnInfo(name = "_id")
|
||||||
|
@ -4,6 +4,7 @@ import android.net.Uri
|
|||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.core.JsonToken
|
import com.fasterxml.jackson.core.JsonToken
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.utility.extension.json.*
|
import com.looker.droidify.utility.extension.json.*
|
||||||
|
|
||||||
data class Release(
|
data class Release(
|
||||||
|
@ -1,312 +0,0 @@
|
|||||||
package com.looker.droidify.entity
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
|
||||||
import com.looker.droidify.utility.extension.json.collectNotNullStrings
|
|
||||||
import com.looker.droidify.utility.extension.json.forEachKey
|
|
||||||
import com.looker.droidify.utility.extension.json.writeArray
|
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
data class Repository(
|
|
||||||
var id: Long, val address: String, val mirrors: List<String>,
|
|
||||||
val name: String, val description: String, val version: Int, var enabled: Boolean,
|
|
||||||
val fingerprint: String, val lastModified: String, val entityTag: String,
|
|
||||||
val updated: Long, val timestamp: Long, val authentication: String,
|
|
||||||
) {
|
|
||||||
fun edit(address: String, fingerprint: String, authentication: String): Repository {
|
|
||||||
val addressChanged = this.address != address
|
|
||||||
val fingerprintChanged = this.fingerprint != fingerprint
|
|
||||||
val changed = addressChanged || fingerprintChanged
|
|
||||||
return copy(
|
|
||||||
address = address,
|
|
||||||
fingerprint = fingerprint,
|
|
||||||
lastModified = if (changed) "" else lastModified,
|
|
||||||
entityTag = if (changed) "" else entityTag,
|
|
||||||
authentication = authentication
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun update(
|
|
||||||
mirrors: List<String>, name: String, description: String, version: Int,
|
|
||||||
lastModified: String, entityTag: String, timestamp: Long,
|
|
||||||
): Repository {
|
|
||||||
return copy(
|
|
||||||
mirrors = mirrors, name = name, description = description,
|
|
||||||
version = if (version >= 0) version else this.version, lastModified = lastModified,
|
|
||||||
entityTag = entityTag, updated = System.currentTimeMillis(), timestamp = timestamp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enable(enabled: Boolean): Repository {
|
|
||||||
return copy(enabled = enabled, lastModified = "", entityTag = "")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun serialize(generator: JsonGenerator) {
|
|
||||||
generator.writeNumberField("serialVersion", 1)
|
|
||||||
generator.writeNumberField("id", id)
|
|
||||||
generator.writeStringField("address", address)
|
|
||||||
generator.writeArray("mirrors") { mirrors.forEach { writeString(it) } }
|
|
||||||
generator.writeStringField("name", name)
|
|
||||||
generator.writeStringField("description", description)
|
|
||||||
generator.writeNumberField("version", version)
|
|
||||||
generator.writeBooleanField("enabled", enabled)
|
|
||||||
generator.writeStringField("fingerprint", fingerprint)
|
|
||||||
generator.writeStringField("lastModified", lastModified)
|
|
||||||
generator.writeStringField("entityTag", entityTag)
|
|
||||||
generator.writeNumberField("updated", updated)
|
|
||||||
generator.writeNumberField("timestamp", timestamp)
|
|
||||||
generator.writeStringField("authentication", authentication)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun deserialize(parser: JsonParser): Repository {
|
|
||||||
var id = 0L
|
|
||||||
var address = ""
|
|
||||||
var mirrors = emptyList<String>()
|
|
||||||
var name = ""
|
|
||||||
var description = ""
|
|
||||||
var version = 0
|
|
||||||
var enabled = false
|
|
||||||
var fingerprint = ""
|
|
||||||
var lastModified = ""
|
|
||||||
var entityTag = ""
|
|
||||||
var updated = 0L
|
|
||||||
var timestamp = 0L
|
|
||||||
var authentication = ""
|
|
||||||
parser.forEachKey {
|
|
||||||
when {
|
|
||||||
it.string("id") -> id = valueAsLong
|
|
||||||
it.string("address") -> address = valueAsString
|
|
||||||
it.array("mirrors") -> mirrors = collectNotNullStrings()
|
|
||||||
it.string("name") -> name = valueAsString
|
|
||||||
it.string("description") -> description = valueAsString
|
|
||||||
it.number("version") -> version = valueAsInt
|
|
||||||
it.boolean("enabled") -> enabled = valueAsBoolean
|
|
||||||
it.string("fingerprint") -> fingerprint = valueAsString
|
|
||||||
it.string("lastModified") -> lastModified = valueAsString
|
|
||||||
it.string("entityTag") -> entityTag = valueAsString
|
|
||||||
it.number("updated") -> updated = valueAsLong
|
|
||||||
it.number("timestamp") -> timestamp = valueAsLong
|
|
||||||
it.string("authentication") -> authentication = valueAsString
|
|
||||||
else -> skipChildren()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Repository(
|
|
||||||
id, address, mirrors, name, description, version, enabled, fingerprint,
|
|
||||||
lastModified, entityTag, updated, timestamp, authentication
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun newRepository(
|
|
||||||
address: String,
|
|
||||||
fingerprint: String,
|
|
||||||
authentication: String,
|
|
||||||
): Repository {
|
|
||||||
val name = try {
|
|
||||||
URL(address).let { "${it.host}${it.path}" }
|
|
||||||
} catch (e: Exception) {
|
|
||||||
address
|
|
||||||
}
|
|
||||||
return defaultRepository(address, name, "", 0, true, fingerprint, authentication)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun defaultRepository(
|
|
||||||
address: String, name: String, description: String,
|
|
||||||
version: Int, enabled: Boolean, fingerprint: String, authentication: String,
|
|
||||||
): Repository {
|
|
||||||
return Repository(
|
|
||||||
-1, 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", ""
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,9 +4,9 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.looker.droidify.content.Cache
|
import com.looker.droidify.content.Cache
|
||||||
import com.looker.droidify.database.DatabaseX
|
import com.looker.droidify.database.DatabaseX
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.Product
|
import com.looker.droidify.entity.Product
|
||||||
import com.looker.droidify.entity.Release
|
import com.looker.droidify.entity.Release
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.network.Downloader
|
import com.looker.droidify.network.Downloader
|
||||||
import com.looker.droidify.utility.ProgressInputStream
|
import com.looker.droidify.utility.ProgressInputStream
|
||||||
import com.looker.droidify.utility.RxUtils
|
import com.looker.droidify.utility.RxUtils
|
||||||
@ -69,17 +69,15 @@ object RepositoryUpdater {
|
|||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMapSingle {
|
.flatMapSingle {
|
||||||
RxUtils.querySingle {
|
RxUtils.querySingle {
|
||||||
db.repositoryDao.allDisabledDeleted
|
db.repositoryDao.allDisabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.forEach { it ->
|
.forEach { it ->
|
||||||
val newDisabled = it.asSequence().filter { !it.deleted }.map { it.id }.toSet()
|
val newDisabled = it.toSet()
|
||||||
val disabled = newDisabled - lastDisabled
|
val disabled = newDisabled - lastDisabled
|
||||||
lastDisabled = newDisabled
|
lastDisabled = newDisabled
|
||||||
val deleted = it.asSequence().filter { it.deleted }.map { it.id }.toSet()
|
if (disabled.isNotEmpty()) {
|
||||||
if (disabled.isNotEmpty() || deleted.isNotEmpty()) {
|
val pairs = (disabled.asSequence().map { Pair(it, false) }).toSet()
|
||||||
val pairs = (disabled.asSequence().map { Pair(it, false) } +
|
|
||||||
deleted.asSequence().map { Pair(it, true) }).toSet()
|
|
||||||
synchronized(cleanupLock) { db.cleanUp(pairs) }
|
synchronized(cleanupLock) { db.cleanUp(pairs) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package com.looker.droidify.network
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.Product
|
import com.looker.droidify.entity.Product
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.utility.extension.text.nullIfEmpty
|
import com.looker.droidify.utility.extension.text.nullIfEmpty
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
|
@ -17,8 +17,8 @@ import androidx.fragment.app.DialogFragment
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.databinding.EditRepositoryBinding
|
import com.looker.droidify.databinding.EditRepositoryBinding
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.network.Downloader
|
import com.looker.droidify.network.Downloader
|
||||||
import com.looker.droidify.service.Connection
|
import com.looker.droidify.service.Connection
|
||||||
import com.looker.droidify.service.SyncService
|
import com.looker.droidify.service.SyncService
|
||||||
@ -37,7 +37,6 @@ import java.net.URI
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class EditRepositoryFragment() : ScreenFragment() {
|
class EditRepositoryFragment() : ScreenFragment() {
|
||||||
@ -153,7 +152,7 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it)?.trueData }
|
val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it) }
|
||||||
if (repository == null) {
|
if (repository == null) {
|
||||||
val clipboardManager =
|
val clipboardManager =
|
||||||
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
@ -232,7 +231,7 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val list = screenActivity.db.repositoryDao.all.mapNotNull { it.trueData }
|
val list = screenActivity.db.repositoryDao.all
|
||||||
takenAddresses = list.asSequence().filter { it.id != repositoryId }
|
takenAddresses = list.asSequence().filter { it.id != repositoryId }
|
||||||
.flatMap { (it.mirrors + it.address).asSequence() }
|
.flatMap { (it.mirrors + it.address).asSequence() }
|
||||||
.map { it.withoutKnownPath }.toSet()
|
.map { it.withoutKnownPath }.toSet()
|
||||||
@ -448,7 +447,7 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
MessageDialog(MessageDialog.Message.CantEditSyncing).show(childFragmentManager)
|
MessageDialog(MessageDialog.Message.CantEditSyncing).show(childFragmentManager)
|
||||||
invalidateState()
|
invalidateState()
|
||||||
} else {
|
} else {
|
||||||
val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it)?.trueData }
|
val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it) }
|
||||||
?.edit(address, fingerprint, authentication)
|
?.edit(address, fingerprint, authentication)
|
||||||
?: Repository.newRepository(address, fingerprint, authentication)
|
?: Repository.newRepository(address, fingerprint, authentication)
|
||||||
val changedRepository = screenActivity.db.repositoryDao.put(repository)
|
val changedRepository = screenActivity.db.repositoryDao.put(repository)
|
||||||
|
@ -9,7 +9,7 @@ import com.google.android.material.card.MaterialCardView
|
|||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
import com.google.android.material.textview.MaterialTextView
|
import com.google.android.material.textview.MaterialTextView
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.entity.Repository
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.utility.extension.resources.clear
|
import com.looker.droidify.utility.extension.resources.clear
|
||||||
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
||||||
import com.looker.droidify.utility.extension.resources.inflate
|
import com.looker.droidify.utility.extension.resources.inflate
|
||||||
|
@ -98,7 +98,7 @@ class RepositoryFragment() : ScreenFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateRepositoryView() {
|
private fun updateRepositoryView() {
|
||||||
val repository = screenActivity.db.repositoryDao.get(repositoryId)?.trueData
|
val repository = screenActivity.db.repositoryDao.get(repositoryId)
|
||||||
val layout = layout!!
|
val layout = layout!!
|
||||||
layout.removeAllViews()
|
layout.removeAllViews()
|
||||||
if (repository == null) {
|
if (repository == null) {
|
||||||
|
@ -10,8 +10,8 @@ import coil.load
|
|||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.Product
|
import com.looker.droidify.entity.Product
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.graphics.PaddingDrawable
|
import com.looker.droidify.graphics.PaddingDrawable
|
||||||
import com.looker.droidify.network.CoilDownloader
|
import com.looker.droidify.network.CoilDownloader
|
||||||
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
||||||
|
@ -20,8 +20,8 @@ import coil.load
|
|||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.database.DatabaseX
|
import com.looker.droidify.database.DatabaseX
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.Product
|
import com.looker.droidify.entity.Product
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.graphics.PaddingDrawable
|
import com.looker.droidify.graphics.PaddingDrawable
|
||||||
import com.looker.droidify.network.CoilDownloader
|
import com.looker.droidify.network.CoilDownloader
|
||||||
import com.looker.droidify.utility.RxUtils
|
import com.looker.droidify.utility.RxUtils
|
||||||
@ -143,7 +143,7 @@ class ScreenshotsFragment() : DialogFragment() {
|
|||||||
.map { it ->
|
.map { it ->
|
||||||
Pair(
|
Pair(
|
||||||
it.find { it.repositoryId == repositoryId },
|
it.find { it.repositoryId == repositoryId },
|
||||||
db.repositoryDao.get(repositoryId)?.trueData
|
db.repositoryDao.get(repositoryId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -246,7 +246,7 @@ class TabsFragment : ScreenFragment() {
|
|||||||
repositoriesDisposable = Observable.just(Unit)
|
repositoriesDisposable = Observable.just(Unit)
|
||||||
//.concatWith(Database.observable(Database.Subject.Repositories)) // TODO have to be replaced like whole rxJava
|
//.concatWith(Database.observable(Database.Subject.Repositories)) // TODO have to be replaced like whole rxJava
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMapSingle { RxUtils.querySingle { screenActivity.db.repositoryDao.all.mapNotNull { it.trueData } } }
|
.flatMapSingle { RxUtils.querySingle { screenActivity.db.repositoryDao.all } }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { it ->
|
.subscribe { it ->
|
||||||
setSectionsAndUpdate(null, it.asSequence().filter { it.enabled }
|
setSectionsAndUpdate(null, it.asSequence().filter { it.enabled }
|
||||||
|
@ -9,21 +9,32 @@ import android.view.ContextThemeWrapper
|
|||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import com.looker.droidify.*
|
import com.looker.droidify.*
|
||||||
import com.looker.droidify.content.Cache
|
import com.looker.droidify.content.Cache
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.Release
|
import com.looker.droidify.entity.Release
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.installer.AppInstaller
|
import com.looker.droidify.installer.AppInstaller
|
||||||
import com.looker.droidify.network.Downloader
|
import com.looker.droidify.network.Downloader
|
||||||
import com.looker.droidify.utility.Utils
|
import com.looker.droidify.utility.Utils
|
||||||
import com.looker.droidify.utility.extension.android.*
|
import com.looker.droidify.utility.extension.android.Android
|
||||||
import com.looker.droidify.utility.extension.resources.*
|
import com.looker.droidify.utility.extension.android.notificationManager
|
||||||
import com.looker.droidify.utility.extension.text.*
|
import com.looker.droidify.utility.extension.android.singleSignature
|
||||||
|
import com.looker.droidify.utility.extension.android.versionCodeCompat
|
||||||
|
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
||||||
|
import com.looker.droidify.utility.extension.text.formatSize
|
||||||
|
import com.looker.droidify.utility.extension.text.hex
|
||||||
|
import com.looker.droidify.utility.extension.text.nullIfEmpty
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.disposables.Disposable
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import kotlin.math.*
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class DownloadService : ConnectionService<DownloadService.Binder>() {
|
class DownloadService : ConnectionService<DownloadService.Binder>() {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -15,8 +15,8 @@ import androidx.fragment.app.Fragment
|
|||||||
import com.looker.droidify.*
|
import com.looker.droidify.*
|
||||||
import com.looker.droidify.content.Preferences
|
import com.looker.droidify.content.Preferences
|
||||||
import com.looker.droidify.database.DatabaseX
|
import com.looker.droidify.database.DatabaseX
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.index.RepositoryUpdater
|
import com.looker.droidify.index.RepositoryUpdater
|
||||||
import com.looker.droidify.utility.RxUtils
|
import com.looker.droidify.utility.RxUtils
|
||||||
import com.looker.droidify.utility.Utils
|
import com.looker.droidify.utility.Utils
|
||||||
@ -100,7 +100,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
|
|
||||||
fun sync(request: SyncRequest) {
|
fun sync(request: SyncRequest) {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
val ids = db.repositoryDao.all.mapNotNull { it.trueData }
|
val ids = db.repositoryDao.all
|
||||||
.asSequence().filter { it.enabled }.map { it.id }.toList()
|
.asSequence().filter { it.enabled }.map { it.id }.toList()
|
||||||
sync(ids, request)
|
sync(ids, request)
|
||||||
}
|
}
|
||||||
@ -146,10 +146,10 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deleteRepository(repositoryId: Long): Boolean {
|
fun deleteRepository(repositoryId: Long): Boolean {
|
||||||
val repository = db.repositoryDao.get(repositoryId)?.trueData
|
val repository = db.repositoryDao.get(repositoryId)
|
||||||
return repository != null && run {
|
return repository != null && run {
|
||||||
setEnabled(repository, false)
|
setEnabled(repository, false)
|
||||||
db.repositoryDao.markAsDeleted(repository.id)
|
db.repositoryDao.deleteById(repository.id)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,7 +337,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
if (tasks.isNotEmpty()) {
|
if (tasks.isNotEmpty()) {
|
||||||
val task = tasks.removeAt(0)
|
val task = tasks.removeAt(0)
|
||||||
val repository = db.repositoryDao.get(task.repositoryId)?.trueData
|
val repository = db.repositoryDao.get(task.repositoryId)
|
||||||
if (repository != null && repository.enabled) {
|
if (repository != null && repository.enabled) {
|
||||||
val lastStarted = started
|
val lastStarted = started
|
||||||
val newStarted =
|
val newStarted =
|
||||||
@ -454,7 +454,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
installedItem.package_name
|
installedItem.package_name
|
||||||
)
|
)
|
||||||
.filter { product -> product?.repository_id == repository.id }
|
.filter { product -> product?.repository_id == repository.id }
|
||||||
.map { product -> Pair(product?.data!!, repository.data!!) }
|
.map { product -> Pair(product?.data!!, repository) }
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
Utils.startUpdate(
|
Utils.startUpdate(
|
||||||
|
@ -44,20 +44,23 @@ import com.looker.droidify.R
|
|||||||
import com.looker.droidify.content.Preferences
|
import com.looker.droidify.content.Preferences
|
||||||
import com.looker.droidify.content.ProductPreferences
|
import com.looker.droidify.content.ProductPreferences
|
||||||
import com.looker.droidify.database.entity.Installed
|
import com.looker.droidify.database.entity.Installed
|
||||||
import com.looker.droidify.entity.*
|
import com.looker.droidify.database.entity.Repository
|
||||||
|
import com.looker.droidify.entity.Product
|
||||||
|
import com.looker.droidify.entity.ProductPreference
|
||||||
|
import com.looker.droidify.entity.Release
|
||||||
import com.looker.droidify.network.CoilDownloader
|
import com.looker.droidify.network.CoilDownloader
|
||||||
import com.looker.droidify.screen.ScreenshotsAdapter
|
import com.looker.droidify.screen.ScreenshotsAdapter
|
||||||
import com.looker.droidify.utility.KParcelable
|
import com.looker.droidify.utility.KParcelable
|
||||||
import com.looker.droidify.utility.PackageItemResolver
|
import com.looker.droidify.utility.PackageItemResolver
|
||||||
import com.looker.droidify.utility.Utils
|
import com.looker.droidify.utility.Utils
|
||||||
import com.looker.droidify.utility.extension.android.*
|
import com.looker.droidify.utility.extension.android.Android
|
||||||
import com.looker.droidify.utility.extension.resources.*
|
import com.looker.droidify.utility.extension.resources.*
|
||||||
import com.looker.droidify.utility.extension.text.*
|
import com.looker.droidify.utility.extension.text.*
|
||||||
import com.looker.droidify.widget.ClickableMovementMethod
|
import com.looker.droidify.widget.ClickableMovementMethod
|
||||||
import com.looker.droidify.widget.StableRecyclerAdapter
|
import com.looker.droidify.widget.StableRecyclerAdapter
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.*
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class AppDetailAdapter(private val callbacks: Callbacks) :
|
class AppDetailAdapter(private val callbacks: Callbacks) :
|
||||||
StableRecyclerAdapter<AppDetailAdapter.ViewType, RecyclerView.ViewHolder>() {
|
StableRecyclerAdapter<AppDetailAdapter.ViewType, RecyclerView.ViewHolder>() {
|
||||||
|
@ -16,8 +16,8 @@ import com.google.android.material.progressindicator.CircularProgressIndicator
|
|||||||
import com.google.android.material.textview.MaterialTextView
|
import com.google.android.material.textview.MaterialTextView
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.content.Preferences
|
import com.looker.droidify.content.Preferences
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.network.CoilDownloader
|
import com.looker.droidify.network.CoilDownloader
|
||||||
import com.looker.droidify.utility.Utils
|
import com.looker.droidify.utility.Utils
|
||||||
import com.looker.droidify.utility.extension.resources.*
|
import com.looker.droidify.utility.extension.resources.*
|
||||||
|
@ -17,7 +17,10 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.content.ProductPreferences
|
import com.looker.droidify.content.ProductPreferences
|
||||||
import com.looker.droidify.entity.*
|
import com.looker.droidify.database.entity.Repository
|
||||||
|
import com.looker.droidify.entity.Product
|
||||||
|
import com.looker.droidify.entity.ProductPreference
|
||||||
|
import com.looker.droidify.entity.Release
|
||||||
import com.looker.droidify.installer.AppInstaller
|
import com.looker.droidify.installer.AppInstaller
|
||||||
import com.looker.droidify.screen.MessageDialog
|
import com.looker.droidify.screen.MessageDialog
|
||||||
import com.looker.droidify.screen.ScreenFragment
|
import com.looker.droidify.screen.ScreenFragment
|
||||||
@ -142,7 +145,7 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|||||||
}
|
}
|
||||||
.flatMapSingle { products ->
|
.flatMapSingle { products ->
|
||||||
RxUtils
|
RxUtils
|
||||||
.querySingle { screenActivity.db.repositoryDao.all.mapNotNull { it.trueData } }
|
.querySingle { screenActivity.db.repositoryDao.all }
|
||||||
.map { it ->
|
.map { it ->
|
||||||
it.asSequence().map { Pair(it.id, it) }.toMap()
|
it.asSequence().map { Pair(it.id, it) }.toMap()
|
||||||
.let {
|
.let {
|
||||||
|
@ -83,7 +83,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
|
|||||||
repositoriesDisposable = Observable.just(Unit)
|
repositoriesDisposable = Observable.just(Unit)
|
||||||
//.concatWith(Database.observable(Database.Subject.Repositories)) // TODO have to be replaced like whole rxJava
|
//.concatWith(Database.observable(Database.Subject.Repositories)) // TODO have to be replaced like whole rxJava
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMapSingle { RxUtils.querySingle { screenActivity.db.repositoryDao.all.mapNotNull { it.trueData } } }
|
.flatMapSingle { RxUtils.querySingle { screenActivity.db.repositoryDao.all } }
|
||||||
.map { it.asSequence().map { Pair(it.id, it) }.toMap() }
|
.map { it.asSequence().map { Pair(it.id, it) }.toMap() }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { (recyclerView?.adapter as? AppListAdapter)?.repositories = it }
|
.subscribe { (recyclerView?.adapter as? AppListAdapter)?.repositories = it }
|
||||||
|
@ -133,7 +133,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment() {
|
|||||||
binding.save.setOnClickListener { onSaveRepositoryClick() }
|
binding.save.setOnClickListener { onSaveRepositoryClick() }
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
val list = viewModel.db.repositoryDao.all.mapNotNull { it.trueData }
|
val list = viewModel.db.repositoryDao.all
|
||||||
takenAddresses = list.asSequence().filter { it.id != repositoryId }
|
takenAddresses = list.asSequence().filter { it.id != repositoryId }
|
||||||
.flatMap { (it.mirrors + it.address).asSequence() }
|
.flatMap { (it.mirrors + it.address).asSequence() }
|
||||||
.map { it.withoutKnownPath }.toSet()
|
.map { it.withoutKnownPath }.toSet()
|
||||||
@ -142,7 +142,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateSheet() {
|
override fun updateSheet() {
|
||||||
val repository = viewModel.repo.value?.trueData
|
val repository = viewModel.repo.value
|
||||||
if (repository == null) {
|
if (repository == null) {
|
||||||
val clipboardManager =
|
val clipboardManager =
|
||||||
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
@ -391,7 +391,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment() {
|
|||||||
invalidateState()
|
invalidateState()
|
||||||
} else {
|
} else {
|
||||||
viewModel.updateRepo(
|
viewModel.updateRepo(
|
||||||
viewModel.repo.value?.trueData?.copy(
|
viewModel.repo.value?.copy(
|
||||||
address = address,
|
address = address,
|
||||||
fingerprint = fingerprint,
|
fingerprint = fingerprint,
|
||||||
authentication = authentication
|
authentication = authentication
|
||||||
|
@ -6,8 +6,8 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.looker.droidify.database.entity.Product
|
import com.looker.droidify.database.entity.Product
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.databinding.FragmentExploreXBinding
|
import com.looker.droidify.databinding.FragmentExploreXBinding
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.ui.items.VAppItem
|
import com.looker.droidify.ui.items.VAppItem
|
||||||
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
||||||
import com.looker.droidify.utility.RxUtils
|
import com.looker.droidify.utility.RxUtils
|
||||||
@ -43,7 +43,7 @@ class ExploreFragment : MainNavFragmentX() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
viewModel.db.repositoryDao.allFlowable
|
viewModel.db.repositoryDao.allFlowable
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }
|
.flatMapSingle { list -> RxUtils.querySingle { list } }
|
||||||
.map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() }
|
.map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() }
|
||||||
.subscribeOn(AndroidSchedulers.mainThread())
|
.subscribeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { repositories = it }
|
.subscribe { repositories = it }
|
||||||
|
@ -7,8 +7,8 @@ import android.view.ViewGroup
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.looker.droidify.database.entity.Product
|
import com.looker.droidify.database.entity.Product
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.databinding.FragmentInstalledXBinding
|
import com.looker.droidify.databinding.FragmentInstalledXBinding
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.ui.items.HAppItem
|
import com.looker.droidify.ui.items.HAppItem
|
||||||
import com.looker.droidify.ui.items.VAppItem
|
import com.looker.droidify.ui.items.VAppItem
|
||||||
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
||||||
@ -47,7 +47,7 @@ class InstalledFragment : MainNavFragmentX() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
viewModel.db.repositoryDao.allFlowable
|
viewModel.db.repositoryDao.allFlowable
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }
|
.flatMapSingle { list -> RxUtils.querySingle { list } }
|
||||||
.map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() }
|
.map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { repositories = it }
|
.subscribe { repositories = it }
|
||||||
|
@ -7,8 +7,8 @@ import android.view.ViewGroup
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.looker.droidify.database.entity.Product
|
import com.looker.droidify.database.entity.Product
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.databinding.FragmentLatestXBinding
|
import com.looker.droidify.databinding.FragmentLatestXBinding
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.ui.items.HAppItem
|
import com.looker.droidify.ui.items.HAppItem
|
||||||
import com.looker.droidify.ui.items.VAppItem
|
import com.looker.droidify.ui.items.VAppItem
|
||||||
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
||||||
@ -48,7 +48,7 @@ class LatestFragment : MainNavFragmentX() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
viewModel.db.repositoryDao.allFlowable
|
viewModel.db.repositoryDao.allFlowable
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }
|
.flatMapSingle { list -> RxUtils.querySingle { list } }
|
||||||
.map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() }
|
.map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { repositories = it }
|
.subscribe { repositories = it }
|
||||||
|
@ -75,25 +75,24 @@ class PrefsRepositoriesFragment : BaseNavFragment() {
|
|||||||
layoutManager = LinearLayoutManager(context)
|
layoutManager = LinearLayoutManager(context)
|
||||||
adapter = reposFastAdapter
|
adapter = reposFastAdapter
|
||||||
}
|
}
|
||||||
|
binding.addRepository.setOnClickListener { viewModel.addRepository() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupLayout() {
|
override fun setupLayout() {
|
||||||
viewModel.repositories.observe(requireActivity()) {
|
viewModel.repositories.observe(requireActivity()) {
|
||||||
// Function: sync when an enabled repo got edited
|
// Function: sync when an enabled repo got edited
|
||||||
val enabledList = it.filter { it.enabled == 1 }
|
val enabledList = it.filter { it.enabled }
|
||||||
reposItemAdapter.adapterItems.filter(RepoItem::isEnabled).forEach { item ->
|
reposItemAdapter.adapterItems.filter(RepoItem::isEnabled).forEach { item ->
|
||||||
enabledList.firstOrNull { it.trueData?.id == item.item.id }?.let { repo ->
|
enabledList.firstOrNull { it.id == item.item.id }?.let { repo ->
|
||||||
repo.trueData?.let { data ->
|
repo.let { data ->
|
||||||
if (data != item.item) syncConnection.binder?.sync(data)
|
if (data != item.item) syncConnection.binder?.sync(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reposItemAdapter.set(
|
reposItemAdapter.set(
|
||||||
it.sortedBy { repo -> -repo.enabled }
|
it.sortedBy { repo -> !repo.enabled }
|
||||||
.mapNotNull { dbRepo ->
|
.mapNotNull { dbRepo ->
|
||||||
dbRepo.trueData?.let { repo ->
|
RepoItem(dbRepo)
|
||||||
RepoItem(repo)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ class RepositorySheetX() : FullscreenBottomSheetDialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateSheet() {
|
override fun updateSheet() {
|
||||||
val repository = viewModel.repo.value?.trueData
|
val repository = viewModel.repo.value
|
||||||
|
|
||||||
if (repository == null) {
|
if (repository == null) {
|
||||||
binding.address.text = getString(R.string.unknown)
|
binding.address.text = getString(R.string.unknown)
|
||||||
|
@ -5,9 +5,9 @@ import android.view.ViewGroup
|
|||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.databinding.ItemAppHorizXBinding
|
import com.looker.droidify.databinding.ItemAppHorizXBinding
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.network.CoilDownloader
|
import com.looker.droidify.network.CoilDownloader
|
||||||
import com.looker.droidify.utility.Utils
|
import com.looker.droidify.utility.Utils
|
||||||
import com.looker.droidify.utility.extension.resources.toPx
|
import com.looker.droidify.utility.extension.resources.toPx
|
||||||
|
@ -5,8 +5,8 @@ import android.view.LayoutInflater
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import coil.load
|
import coil.load
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.databinding.ItemRepositoryXBinding
|
import com.looker.droidify.databinding.ItemRepositoryXBinding
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.utility.extension.resources.clear
|
import com.looker.droidify.utility.extension.resources.clear
|
||||||
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
||||||
import com.mikepenz.fastadapter.binding.AbstractBindingItem
|
import com.mikepenz.fastadapter.binding.AbstractBindingItem
|
||||||
|
@ -7,9 +7,9 @@ import androidx.core.content.res.ResourcesCompat
|
|||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.databinding.ItemAppVerticalXBinding
|
import com.looker.droidify.databinding.ItemAppVerticalXBinding
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.network.CoilDownloader
|
import com.looker.droidify.network.CoilDownloader
|
||||||
import com.looker.droidify.utility.Utils
|
import com.looker.droidify.utility.Utils
|
||||||
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
import com.looker.droidify.utility.extension.resources.getColorFromAttr
|
||||||
|
@ -20,7 +20,7 @@ class RepositoryViewModelX(val db: DatabaseX, val repositoryId: Long) : ViewMode
|
|||||||
appsCount.addSource(db.productDao.countForRepositoryLive(repositoryId), appsCount::setValue)
|
appsCount.addSource(db.productDao.countForRepositoryLive(repositoryId), appsCount::setValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateRepo(newValue: com.looker.droidify.entity.Repository?) {
|
fun updateRepo(newValue: Repository?) {
|
||||||
newValue?.let {
|
newValue?.let {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
update(it)
|
update(it)
|
||||||
@ -28,7 +28,7 @@ class RepositoryViewModelX(val db: DatabaseX, val repositoryId: Long) : ViewMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun update(newValue: com.looker.droidify.entity.Repository) {
|
private suspend fun update(newValue: Repository) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
db.repositoryDao.put(newValue)
|
db.repositoryDao.put(newValue)
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,10 @@ import com.fasterxml.jackson.core.JsonParser
|
|||||||
import com.looker.droidify.*
|
import com.looker.droidify.*
|
||||||
import com.looker.droidify.content.Preferences
|
import com.looker.droidify.content.Preferences
|
||||||
import com.looker.droidify.database.entity.Installed
|
import com.looker.droidify.database.entity.Installed
|
||||||
|
import com.looker.droidify.database.entity.Repository
|
||||||
import com.looker.droidify.entity.InstalledItem
|
import com.looker.droidify.entity.InstalledItem
|
||||||
import com.looker.droidify.entity.Product
|
import com.looker.droidify.entity.Product
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import com.looker.droidify.entity.Repository
|
|
||||||
import com.looker.droidify.service.Connection
|
import com.looker.droidify.service.Connection
|
||||||
import com.looker.droidify.service.DownloadService
|
import com.looker.droidify.service.DownloadService
|
||||||
import com.looker.droidify.utility.extension.android.Android
|
import com.looker.droidify.utility.extension.android.Android
|
||||||
|
Loading…
x
Reference in New Issue
Block a user