Update: Merge Repository's entity and database.entity classes

+ Update related DAOs
+ Add needed converters
+ Fix calls
This commit is contained in:
machiav3lli 2022-01-28 00:31:27 +01:00
parent 050ecfd4a0
commit 7bbac86dd4
32 changed files with 418 additions and 419 deletions

View File

@ -214,7 +214,7 @@ class MainApplication : Application(), ImageLoaderFactory {
}
private fun forceSyncAll() {
db.repositoryDao.all.mapNotNull { it.trueData }.forEach {
db.repositoryDao.all.forEach {
if (it.lastModified.isNotEmpty() || it.entityTag.isNotEmpty()) {
db.repositoryDao.put(it.copy(lastModified = "", entityTag = ""))
}

View File

@ -2,18 +2,21 @@ package com.looker.droidify.database
import androidx.room.TypeConverter
import com.looker.droidify.entity.ProductItem
import com.looker.droidify.entity.Repository
import com.looker.droidify.utility.jsonGenerate
import com.looker.droidify.utility.jsonParse
object Converters {
@TypeConverter
@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
@JvmStatic
fun toByteArray(repository: Repository) = jsonGenerate(repository::serialize)
fun toString(list: List<String>): ByteArray = list.toString().toByteArray()
@TypeConverter
@JvmStatic

View File

@ -32,15 +32,9 @@ interface RepositoryDao : BaseDao<Repository> {
@get:Query("SELECT COUNT(_id) FROM repository")
val count: Int
fun put(repository: com.looker.droidify.entity.Repository): com.looker.droidify.entity.Repository {
repository.let {
val dbRepo = Repository().apply {
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)
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
}
}
@ -48,35 +42,30 @@ interface RepositoryDao : BaseDao<Repository> {
@Insert
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?
@Query("SELECT * FROM repository WHERE _id = :id and deleted == 0")
@Query("SELECT * FROM repository WHERE _id = :id")
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
@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>
@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>>
@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>>
@get:Query("SELECT _id, deleted FROM repository WHERE deleted != 0 and enabled == 0 ORDER BY _id ASC")
val allDisabledDeleted: List<Repository.IdAndDeleted>
@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): Int
// TODO optimize
@Update(onConflict = OnConflictStrategy.REPLACE)
fun markAsDeleted(id: Long) {
get(id).apply { this?.deleted = true }?.let { update(it) }
}
}
@Dao
@ -148,8 +137,7 @@ interface ProductDao : BaseDao<Product> {
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
}
builder += """WHERE repository.${ROW_ENABLED} != 0 AND
repository.${ROW_DELETED} == 0"""
builder += """WHERE repository.${ROW_ENABLED} != 0"""
if (section is ProductItem.Section.Category) {
builder += "AND category.${ROW_NAME} = ?"
@ -238,8 +226,7 @@ interface ProductDao : BaseDao<Product> {
ON product.${ROW_PACKAGE_NAME} = category.${ROW_PACKAGE_NAME}"""
}
builder += """WHERE repository.${ROW_ENABLED} != 0 AND
repository.${ROW_DELETED} == 0"""
builder += """WHERE repository.${ROW_ENABLED} != 0"""
if (section is ProductItem.Section.Category) {
builder += "AND category.${ROW_NAME} = ?"
@ -282,8 +269,7 @@ interface CategoryDao : BaseDao<Category> {
FROM category AS category
JOIN repository AS repository
ON category.repository_id = repository._id
WHERE repository.enabled != 0 AND
repository.deleted == 0"""
WHERE repository.enabled != 0"""
)
val allNames: List<String>

View File

@ -6,7 +6,7 @@ import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
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.GlobalScope
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 {
if (success) {
productDao.deleteById(repository.id)

View File

@ -3,23 +3,331 @@ package com.looker.droidify.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
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
class Repository {
data class Repository(
@PrimaryKey(autoGenerate = true)
@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
var deleted = false
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
}
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
var data: Repository? = null
fun enable(enabled: Boolean): Repository = apply {
this.enabled = enabled
this.lastModified = ""
this.entityTag = ""
}
val trueData: Repository?
get() = data?.copy(id = id)
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 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")

View File

@ -4,6 +4,7 @@ import android.net.Uri
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.utility.extension.json.*
data class Release(

View File

@ -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", ""
)
})
}
}

View File

@ -4,9 +4,9 @@ import android.content.Context
import android.net.Uri
import com.looker.droidify.content.Cache
import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.Product
import com.looker.droidify.entity.Release
import com.looker.droidify.entity.Repository
import com.looker.droidify.network.Downloader
import com.looker.droidify.utility.ProgressInputStream
import com.looker.droidify.utility.RxUtils
@ -69,17 +69,15 @@ object RepositoryUpdater {
.observeOn(Schedulers.io())
.flatMapSingle {
RxUtils.querySingle {
db.repositoryDao.allDisabledDeleted
db.repositoryDao.allDisabled
}
}
.forEach { it ->
val newDisabled = it.asSequence().filter { !it.deleted }.map { it.id }.toSet()
val newDisabled = it.toSet()
val disabled = newDisabled - lastDisabled
lastDisabled = newDisabled
val deleted = it.asSequence().filter { it.deleted }.map { it.id }.toSet()
if (disabled.isNotEmpty() || deleted.isNotEmpty()) {
val pairs = (disabled.asSequence().map { Pair(it, false) } +
deleted.asSequence().map { Pair(it, true) }).toSet()
if (disabled.isNotEmpty()) {
val pairs = (disabled.asSequence().map { Pair(it, false) }).toSet()
synchronized(cleanupLock) { db.cleanUp(pairs) }
}
}

View File

@ -3,8 +3,8 @@ package com.looker.droidify.network
import android.content.Context
import android.net.Uri
import android.view.View
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.Product
import com.looker.droidify.entity.Repository
import com.looker.droidify.utility.extension.text.nullIfEmpty
import okhttp3.Cache
import okhttp3.Call

View File

@ -17,8 +17,8 @@ import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.looker.droidify.R
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.databinding.EditRepositoryBinding
import com.looker.droidify.entity.Repository
import com.looker.droidify.network.Downloader
import com.looker.droidify.service.Connection
import com.looker.droidify.service.SyncService
@ -37,7 +37,6 @@ import java.net.URI
import java.net.URL
import java.nio.charset.Charset
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.min
class EditRepositoryFragment() : ScreenFragment() {
@ -153,7 +152,7 @@ class EditRepositoryFragment() : ScreenFragment() {
}
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) {
val clipboardManager =
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
@ -232,7 +231,7 @@ class EditRepositoryFragment() : ScreenFragment() {
}
lifecycleScope.launch {
val list = screenActivity.db.repositoryDao.all.mapNotNull { it.trueData }
val list = screenActivity.db.repositoryDao.all
takenAddresses = list.asSequence().filter { it.id != repositoryId }
.flatMap { (it.mirrors + it.address).asSequence() }
.map { it.withoutKnownPath }.toSet()
@ -448,7 +447,7 @@ class EditRepositoryFragment() : ScreenFragment() {
MessageDialog(MessageDialog.Message.CantEditSyncing).show(childFragmentManager)
invalidateState()
} else {
val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it)?.trueData }
val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it) }
?.edit(address, fingerprint, authentication)
?: Repository.newRepository(address, fingerprint, authentication)
val changedRepository = screenActivity.db.repositoryDao.put(repository)

View File

@ -9,7 +9,7 @@ import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.textview.MaterialTextView
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.getColorFromAttr
import com.looker.droidify.utility.extension.resources.inflate

View File

@ -98,7 +98,7 @@ class RepositoryFragment() : ScreenFragment() {
}
private fun updateRepositoryView() {
val repository = screenActivity.db.repositoryDao.get(repositoryId)?.trueData
val repository = screenActivity.db.repositoryDao.get(repositoryId)
val layout = layout!!
layout.removeAllViews()
if (repository == null) {

View File

@ -10,8 +10,8 @@ import coil.load
import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView
import com.looker.droidify.R
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.Product
import com.looker.droidify.entity.Repository
import com.looker.droidify.graphics.PaddingDrawable
import com.looker.droidify.network.CoilDownloader
import com.looker.droidify.utility.extension.resources.getColorFromAttr

View File

@ -20,8 +20,8 @@ import coil.load
import com.google.android.material.imageview.ShapeableImageView
import com.looker.droidify.R
import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.Product
import com.looker.droidify.entity.Repository
import com.looker.droidify.graphics.PaddingDrawable
import com.looker.droidify.network.CoilDownloader
import com.looker.droidify.utility.RxUtils
@ -143,7 +143,7 @@ class ScreenshotsFragment() : DialogFragment() {
.map { it ->
Pair(
it.find { it.repositoryId == repositoryId },
db.repositoryDao.get(repositoryId)?.trueData
db.repositoryDao.get(repositoryId)
)
}
.observeOn(AndroidSchedulers.mainThread())

View File

@ -246,7 +246,7 @@ class TabsFragment : ScreenFragment() {
repositoriesDisposable = Observable.just(Unit)
//.concatWith(Database.observable(Database.Subject.Repositories)) // TODO have to be replaced like whole rxJava
.observeOn(Schedulers.io())
.flatMapSingle { RxUtils.querySingle { screenActivity.db.repositoryDao.all.mapNotNull { it.trueData } } }
.flatMapSingle { RxUtils.querySingle { screenActivity.db.repositoryDao.all } }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { it ->
setSectionsAndUpdate(null, it.asSequence().filter { it.enabled }

View File

@ -9,21 +9,32 @@ import android.view.ContextThemeWrapper
import androidx.core.app.NotificationCompat
import com.looker.droidify.*
import com.looker.droidify.content.Cache
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.Release
import com.looker.droidify.entity.Repository
import com.looker.droidify.installer.AppInstaller
import com.looker.droidify.network.Downloader
import com.looker.droidify.utility.Utils
import com.looker.droidify.utility.extension.android.*
import com.looker.droidify.utility.extension.resources.*
import com.looker.droidify.utility.extension.text.*
import com.looker.droidify.utility.extension.android.Android
import com.looker.droidify.utility.extension.android.notificationManager
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.disposables.Disposable
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.CoroutineScope
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.security.MessageDigest
import kotlin.math.*
import kotlin.math.roundToInt
class DownloadService : ConnectionService<DownloadService.Binder>() {
companion object {

View File

@ -15,8 +15,8 @@ import androidx.fragment.app.Fragment
import com.looker.droidify.*
import com.looker.droidify.content.Preferences
import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.ProductItem
import com.looker.droidify.entity.Repository
import com.looker.droidify.index.RepositoryUpdater
import com.looker.droidify.utility.RxUtils
import com.looker.droidify.utility.Utils
@ -100,7 +100,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
fun sync(request: SyncRequest) {
GlobalScope.launch {
val ids = db.repositoryDao.all.mapNotNull { it.trueData }
val ids = db.repositoryDao.all
.asSequence().filter { it.enabled }.map { it.id }.toList()
sync(ids, request)
}
@ -146,10 +146,10 @@ class SyncService : ConnectionService<SyncService.Binder>() {
}
fun deleteRepository(repositoryId: Long): Boolean {
val repository = db.repositoryDao.get(repositoryId)?.trueData
val repository = db.repositoryDao.get(repositoryId)
return repository != null && run {
setEnabled(repository, false)
db.repositoryDao.markAsDeleted(repository.id)
db.repositoryDao.deleteById(repository.id)
true
}
}
@ -337,7 +337,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
GlobalScope.launch {
if (tasks.isNotEmpty()) {
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) {
val lastStarted = started
val newStarted =
@ -454,7 +454,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
installedItem.package_name
)
.filter { product -> product?.repository_id == repository.id }
.map { product -> Pair(product?.data!!, repository.data!!) }
.map { product -> Pair(product?.data!!, repository) }
scope.launch {
Utils.startUpdate(

View File

@ -44,20 +44,23 @@ import com.looker.droidify.R
import com.looker.droidify.content.Preferences
import com.looker.droidify.content.ProductPreferences
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.screen.ScreenshotsAdapter
import com.looker.droidify.utility.KParcelable
import com.looker.droidify.utility.PackageItemResolver
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.text.*
import com.looker.droidify.widget.ClickableMovementMethod
import com.looker.droidify.widget.StableRecyclerAdapter
import java.lang.ref.WeakReference
import java.util.*
import kotlin.math.*
import kotlin.math.roundToInt
class AppDetailAdapter(private val callbacks: Callbacks) :
StableRecyclerAdapter<AppDetailAdapter.ViewType, RecyclerView.ViewHolder>() {

View File

@ -16,8 +16,8 @@ import com.google.android.material.progressindicator.CircularProgressIndicator
import com.google.android.material.textview.MaterialTextView
import com.looker.droidify.R
import com.looker.droidify.content.Preferences
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.entity.ProductItem
import com.looker.droidify.entity.Repository
import com.looker.droidify.network.CoilDownloader
import com.looker.droidify.utility.Utils
import com.looker.droidify.utility.extension.resources.*

View File

@ -17,7 +17,10 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.looker.droidify.R
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.screen.MessageDialog
import com.looker.droidify.screen.ScreenFragment
@ -142,7 +145,7 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
}
.flatMapSingle { products ->
RxUtils
.querySingle { screenActivity.db.repositoryDao.all.mapNotNull { it.trueData } }
.querySingle { screenActivity.db.repositoryDao.all }
.map { it ->
it.asSequence().map { Pair(it.id, it) }.toMap()
.let {

View File

@ -83,7 +83,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
repositoriesDisposable = Observable.just(Unit)
//.concatWith(Database.observable(Database.Subject.Repositories)) // TODO have to be replaced like whole rxJava
.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() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { (recyclerView?.adapter as? AppListAdapter)?.repositories = it }

View File

@ -133,7 +133,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment() {
binding.save.setOnClickListener { onSaveRepositoryClick() }
GlobalScope.launch {
val list = viewModel.db.repositoryDao.all.mapNotNull { it.trueData }
val list = viewModel.db.repositoryDao.all
takenAddresses = list.asSequence().filter { it.id != repositoryId }
.flatMap { (it.mirrors + it.address).asSequence() }
.map { it.withoutKnownPath }.toSet()
@ -142,7 +142,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment() {
}
override fun updateSheet() {
val repository = viewModel.repo.value?.trueData
val repository = viewModel.repo.value
if (repository == null) {
val clipboardManager =
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
@ -391,7 +391,7 @@ class EditRepositorySheetX() : FullscreenBottomSheetDialogFragment() {
invalidateState()
} else {
viewModel.updateRepo(
viewModel.repo.value?.trueData?.copy(
viewModel.repo.value?.copy(
address = address,
fingerprint = fingerprint,
authentication = authentication

View File

@ -6,8 +6,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.looker.droidify.database.entity.Product
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.databinding.FragmentExploreXBinding
import com.looker.droidify.entity.Repository
import com.looker.droidify.ui.items.VAppItem
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
import com.looker.droidify.utility.RxUtils
@ -43,7 +43,7 @@ class ExploreFragment : MainNavFragmentX() {
super.onViewCreated(view, savedInstanceState)
viewModel.db.repositoryDao.allFlowable
.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() }
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe { repositories = it }

View File

@ -7,8 +7,8 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.looker.droidify.database.entity.Product
import com.looker.droidify.database.entity.Repository
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.VAppItem
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
@ -47,7 +47,7 @@ class InstalledFragment : MainNavFragmentX() {
super.onViewCreated(view, savedInstanceState)
viewModel.db.repositoryDao.allFlowable
.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() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { repositories = it }

View File

@ -7,8 +7,8 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.looker.droidify.database.entity.Product
import com.looker.droidify.database.entity.Repository
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.VAppItem
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
@ -48,7 +48,7 @@ class LatestFragment : MainNavFragmentX() {
super.onViewCreated(view, savedInstanceState)
viewModel.db.repositoryDao.allFlowable
.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() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { repositories = it }

View File

@ -75,25 +75,24 @@ class PrefsRepositoriesFragment : BaseNavFragment() {
layoutManager = LinearLayoutManager(context)
adapter = reposFastAdapter
}
binding.addRepository.setOnClickListener { viewModel.addRepository() }
}
override fun setupLayout() {
viewModel.repositories.observe(requireActivity()) {
// 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 ->
enabledList.firstOrNull { it.trueData?.id == item.item.id }?.let { repo ->
repo.trueData?.let { data ->
enabledList.firstOrNull { it.id == item.item.id }?.let { repo ->
repo.let { data ->
if (data != item.item) syncConnection.binder?.sync(data)
}
}
}
reposItemAdapter.set(
it.sortedBy { repo -> -repo.enabled }
it.sortedBy { repo -> !repo.enabled }
.mapNotNull { dbRepo ->
dbRepo.trueData?.let { repo ->
RepoItem(repo)
}
RepoItem(dbRepo)
}
)
}

View File

@ -71,7 +71,7 @@ class RepositorySheetX() : FullscreenBottomSheetDialogFragment() {
}
override fun updateSheet() {
val repository = viewModel.repo.value?.trueData
val repository = viewModel.repo.value
if (repository == null) {
binding.address.text = getString(R.string.unknown)

View File

@ -5,9 +5,9 @@ import android.view.ViewGroup
import coil.load
import coil.transform.RoundedCornersTransformation
import com.looker.droidify.R
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.databinding.ItemAppHorizXBinding
import com.looker.droidify.entity.ProductItem
import com.looker.droidify.entity.Repository
import com.looker.droidify.network.CoilDownloader
import com.looker.droidify.utility.Utils
import com.looker.droidify.utility.extension.resources.toPx

View File

@ -5,8 +5,8 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import coil.load
import com.looker.droidify.R
import com.looker.droidify.database.entity.Repository
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.getColorFromAttr
import com.mikepenz.fastadapter.binding.AbstractBindingItem

View File

@ -7,9 +7,9 @@ import androidx.core.content.res.ResourcesCompat
import coil.load
import coil.transform.RoundedCornersTransformation
import com.looker.droidify.R
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.databinding.ItemAppVerticalXBinding
import com.looker.droidify.entity.ProductItem
import com.looker.droidify.entity.Repository
import com.looker.droidify.network.CoilDownloader
import com.looker.droidify.utility.Utils
import com.looker.droidify.utility.extension.resources.getColorFromAttr

View File

@ -20,7 +20,7 @@ class RepositoryViewModelX(val db: DatabaseX, val repositoryId: Long) : ViewMode
appsCount.addSource(db.productDao.countForRepositoryLive(repositoryId), appsCount::setValue)
}
fun updateRepo(newValue: com.looker.droidify.entity.Repository?) {
fun updateRepo(newValue: Repository?) {
newValue?.let {
viewModelScope.launch {
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) {
db.repositoryDao.put(newValue)
}

View File

@ -17,10 +17,10 @@ import com.fasterxml.jackson.core.JsonParser
import com.looker.droidify.*
import com.looker.droidify.content.Preferences
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.Product
import com.looker.droidify.entity.ProductItem
import com.looker.droidify.entity.Repository
import com.looker.droidify.service.Connection
import com.looker.droidify.service.DownloadService
import com.looker.droidify.utility.extension.android.Android