diff --git a/src/main/kotlin/com/looker/droidify/MainApplication.kt b/src/main/kotlin/com/looker/droidify/MainApplication.kt index 96804b76..4b2293f6 100644 --- a/src/main/kotlin/com/looker/droidify/MainApplication.kt +++ b/src/main/kotlin/com/looker/droidify/MainApplication.kt @@ -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 = "")) } diff --git a/src/main/kotlin/com/looker/droidify/database/Converters.kt b/src/main/kotlin/com/looker/droidify/database/Converters.kt index 5d1c607a..7b15534b 100644 --- a/src/main/kotlin/com/looker/droidify/database/Converters.kt +++ b/src/main/kotlin/com/looker/droidify/database/Converters.kt @@ -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 { + val string = byteArray.toString() + return if (string == "") emptyList() + else string.split(",") + } @TypeConverter @JvmStatic - fun toByteArray(repository: Repository) = jsonGenerate(repository::serialize) + fun toString(list: List): ByteArray = list.toString().toByteArray() @TypeConverter @JvmStatic diff --git a/src/main/kotlin/com/looker/droidify/database/DAOs.kt b/src/main/kotlin/com/looker/droidify/database/DAOs.kt index 2f62c267..bd0f844b 100644 --- a/src/main/kotlin/com/looker/droidify/database/DAOs.kt +++ b/src/main/kotlin/com/looker/droidify/database/DAOs.kt @@ -32,15 +32,9 @@ interface RepositoryDao : BaseDao { @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 { @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 - @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 - @get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC") + @get:Query("SELECT * FROM repository ORDER BY _id ASC") val allLive: LiveData> - @get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC") + @get:Query("SELECT * FROM repository ORDER BY _id ASC") val allFlowable: Flowable> - @get:Query("SELECT _id, deleted FROM repository WHERE deleted != 0 and enabled == 0 ORDER BY _id ASC") - val allDisabledDeleted: List + @get:Query("SELECT _id FROM repository WHERE enabled == 0 ORDER BY _id ASC") + val allDisabled: List + // 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 { 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 { 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 { 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 diff --git a/src/main/kotlin/com/looker/droidify/database/DatabaseX.kt b/src/main/kotlin/com/looker/droidify/database/DatabaseX.kt index 15d9836a..77485af9 100644 --- a/src/main/kotlin/com/looker/droidify/database/DatabaseX.kt +++ b/src/main/kotlin/com/looker/droidify/database/DatabaseX.kt @@ -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) diff --git a/src/main/kotlin/com/looker/droidify/database/entity/Repository.kt b/src/main/kotlin/com/looker/droidify/database/entity/Repository.kt index 0350c632..6fc27c95 100644 --- a/src/main/kotlin/com/looker/droidify/database/entity/Repository.kt +++ b/src/main/kotlin/com/looker/droidify/database/entity/Repository.kt @@ -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 = 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, 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() + 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") diff --git a/src/main/kotlin/com/looker/droidify/entity/Release.kt b/src/main/kotlin/com/looker/droidify/entity/Release.kt index 5eb8e628..1e487a70 100644 --- a/src/main/kotlin/com/looker/droidify/entity/Release.kt +++ b/src/main/kotlin/com/looker/droidify/entity/Release.kt @@ -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( diff --git a/src/main/kotlin/com/looker/droidify/entity/Repository.kt b/src/main/kotlin/com/looker/droidify/entity/Repository.kt deleted file mode 100644 index 8053d2e0..00000000 --- a/src/main/kotlin/com/looker/droidify/entity/Repository.kt +++ /dev/null @@ -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, - 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, 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() - 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", "" - ) - }) - } -} diff --git a/src/main/kotlin/com/looker/droidify/index/RepositoryUpdater.kt b/src/main/kotlin/com/looker/droidify/index/RepositoryUpdater.kt index 15270351..e8b1fb68 100644 --- a/src/main/kotlin/com/looker/droidify/index/RepositoryUpdater.kt +++ b/src/main/kotlin/com/looker/droidify/index/RepositoryUpdater.kt @@ -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) } } } diff --git a/src/main/kotlin/com/looker/droidify/network/CoilDownloader.kt b/src/main/kotlin/com/looker/droidify/network/CoilDownloader.kt index 3943a6ba..17ce009a 100644 --- a/src/main/kotlin/com/looker/droidify/network/CoilDownloader.kt +++ b/src/main/kotlin/com/looker/droidify/network/CoilDownloader.kt @@ -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 diff --git a/src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt b/src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt index 4286bfc6..86a5423a 100644 --- a/src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt +++ b/src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt @@ -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) diff --git a/src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt b/src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt index f873d3a2..de0f7283 100644 --- a/src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt +++ b/src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt @@ -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 diff --git a/src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt b/src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt index 472e1691..097fae82 100644 --- a/src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt +++ b/src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt @@ -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) { diff --git a/src/main/kotlin/com/looker/droidify/screen/ScreenshotsAdapter.kt b/src/main/kotlin/com/looker/droidify/screen/ScreenshotsAdapter.kt index c779ffd0..1e292a28 100644 --- a/src/main/kotlin/com/looker/droidify/screen/ScreenshotsAdapter.kt +++ b/src/main/kotlin/com/looker/droidify/screen/ScreenshotsAdapter.kt @@ -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 diff --git a/src/main/kotlin/com/looker/droidify/screen/ScreenshotsFragment.kt b/src/main/kotlin/com/looker/droidify/screen/ScreenshotsFragment.kt index 7520df2e..dc235390 100644 --- a/src/main/kotlin/com/looker/droidify/screen/ScreenshotsFragment.kt +++ b/src/main/kotlin/com/looker/droidify/screen/ScreenshotsFragment.kt @@ -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()) diff --git a/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt b/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt index fdce8c2a..5ad0307b 100644 --- a/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt +++ b/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt @@ -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 } diff --git a/src/main/kotlin/com/looker/droidify/service/DownloadService.kt b/src/main/kotlin/com/looker/droidify/service/DownloadService.kt index 77833c45..67d689d8 100644 --- a/src/main/kotlin/com/looker/droidify/service/DownloadService.kt +++ b/src/main/kotlin/com/looker/droidify/service/DownloadService.kt @@ -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() { companion object { diff --git a/src/main/kotlin/com/looker/droidify/service/SyncService.kt b/src/main/kotlin/com/looker/droidify/service/SyncService.kt index bbc8f079..1a47aa6c 100644 --- a/src/main/kotlin/com/looker/droidify/service/SyncService.kt +++ b/src/main/kotlin/com/looker/droidify/service/SyncService.kt @@ -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() { 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() { } 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() { 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() { 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( diff --git a/src/main/kotlin/com/looker/droidify/ui/adapters/AppDetailAdapter.kt b/src/main/kotlin/com/looker/droidify/ui/adapters/AppDetailAdapter.kt index ed2354d3..1f63d44c 100644 --- a/src/main/kotlin/com/looker/droidify/ui/adapters/AppDetailAdapter.kt +++ b/src/main/kotlin/com/looker/droidify/ui/adapters/AppDetailAdapter.kt @@ -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() { diff --git a/src/main/kotlin/com/looker/droidify/ui/adapters/AppListAdapter.kt b/src/main/kotlin/com/looker/droidify/ui/adapters/AppListAdapter.kt index d9968a16..52780d3b 100644 --- a/src/main/kotlin/com/looker/droidify/ui/adapters/AppListAdapter.kt +++ b/src/main/kotlin/com/looker/droidify/ui/adapters/AppListAdapter.kt @@ -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.* diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/AppDetailFragment.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/AppDetailFragment.kt index 8b57e0d6..bb18b0a8 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/AppDetailFragment.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/AppDetailFragment.kt @@ -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 { diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/AppListFragment.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/AppListFragment.kt index 0b0aa6ba..c8f25920 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/AppListFragment.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/AppListFragment.kt @@ -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 } diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/EditRepositorySheetX.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/EditRepositorySheetX.kt index 6371b8d0..e0b3d6e5 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/EditRepositorySheetX.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/EditRepositorySheetX.kt @@ -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 diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/ExploreFragment.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/ExploreFragment.kt index 3db6d9e5..90abe46c 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/ExploreFragment.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/ExploreFragment.kt @@ -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 } diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/InstalledFragment.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/InstalledFragment.kt index ec4a666e..b050f74c 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/InstalledFragment.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/InstalledFragment.kt @@ -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 } diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/LatestFragment.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/LatestFragment.kt index 96895132..2bd328c0 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/LatestFragment.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/LatestFragment.kt @@ -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 } diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/PrefsRepositoriesFragment.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/PrefsRepositoriesFragment.kt index 1a3398d2..741122af 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/PrefsRepositoriesFragment.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/PrefsRepositoriesFragment.kt @@ -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) } ) } diff --git a/src/main/kotlin/com/looker/droidify/ui/fragments/RepositorySheetX.kt b/src/main/kotlin/com/looker/droidify/ui/fragments/RepositorySheetX.kt index 928705d0..cff1773b 100644 --- a/src/main/kotlin/com/looker/droidify/ui/fragments/RepositorySheetX.kt +++ b/src/main/kotlin/com/looker/droidify/ui/fragments/RepositorySheetX.kt @@ -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) diff --git a/src/main/kotlin/com/looker/droidify/ui/items/HAppItem.kt b/src/main/kotlin/com/looker/droidify/ui/items/HAppItem.kt index 5d12bb58..2db0ccbe 100644 --- a/src/main/kotlin/com/looker/droidify/ui/items/HAppItem.kt +++ b/src/main/kotlin/com/looker/droidify/ui/items/HAppItem.kt @@ -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 diff --git a/src/main/kotlin/com/looker/droidify/ui/items/RepoItem.kt b/src/main/kotlin/com/looker/droidify/ui/items/RepoItem.kt index 1c847848..010036c0 100644 --- a/src/main/kotlin/com/looker/droidify/ui/items/RepoItem.kt +++ b/src/main/kotlin/com/looker/droidify/ui/items/RepoItem.kt @@ -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 diff --git a/src/main/kotlin/com/looker/droidify/ui/items/VAppItem.kt b/src/main/kotlin/com/looker/droidify/ui/items/VAppItem.kt index 2a9a63b9..4b39fa87 100644 --- a/src/main/kotlin/com/looker/droidify/ui/items/VAppItem.kt +++ b/src/main/kotlin/com/looker/droidify/ui/items/VAppItem.kt @@ -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 diff --git a/src/main/kotlin/com/looker/droidify/ui/viewmodels/RepositoryViewModelX.kt b/src/main/kotlin/com/looker/droidify/ui/viewmodels/RepositoryViewModelX.kt index 78a50979..e2224189 100644 --- a/src/main/kotlin/com/looker/droidify/ui/viewmodels/RepositoryViewModelX.kt +++ b/src/main/kotlin/com/looker/droidify/ui/viewmodels/RepositoryViewModelX.kt @@ -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) } diff --git a/src/main/kotlin/com/looker/droidify/utility/Utils.kt b/src/main/kotlin/com/looker/droidify/utility/Utils.kt index d8e07920..b4e414f5 100644 --- a/src/main/kotlin/com/looker/droidify/utility/Utils.kt +++ b/src/main/kotlin/com/looker/droidify/utility/Utils.kt @@ -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