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() {
|
||||
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 = ""))
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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(
|
||||
|
@ -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 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) }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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 }
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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>() {
|
||||
|
@ -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.*
|
||||
|
@ -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 {
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user