From d124f3dec80904946a84f906bceb132c623bd4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E8=87=B4=E9=82=A6=20=28XIE=20Zhibang=29?= Date: Sat, 1 Aug 2026 18:40:36 +0800 Subject: [PATCH] Add isStable to fix startUpdate and startImportInstalledResult --- .../1209.json | 2230 +++++++++++++++++ .../fdroid/data/database/DatabaseX.kt | 23 +- .../data/database/entity/IndexProduct.kt | 3 +- .../fdroid/data/database/entity/Product.kt | 5 +- .../fdroid/data/database/entity/Release.kt | 6 + .../fdroid/data/index/v0/IndexV0Parser.kt | 9 +- .../fdroid/data/index/v1/Converter.kt | 8 +- .../fdroid/data/index/v1/IndexV1Parser.kt | 12 +- .../fdroid/data/index/v2/Converter.kt | 1 + .../fdroid/ui/pages/PrefsOtherPage.kt | 16 +- .../com/machiav3lli/fdroid/utils/Utils.kt | 2 +- 11 files changed, 2290 insertions(+), 25 deletions(-) create mode 100644 schemas/com.machiav3lli.fdroid.data.database.DatabaseX/1209.json diff --git a/schemas/com.machiav3lli.fdroid.data.database.DatabaseX/1209.json b/schemas/com.machiav3lli.fdroid.data.database.DatabaseX/1209.json new file mode 100644 index 0000000000..65f15912f5 --- /dev/null +++ b/schemas/com.machiav3lli.fdroid.data.database.DatabaseX/1209.json @@ -0,0 +1,2230 @@ +{ + "formatVersion": 1, + "database": { + "version": 1209, + "identityHash": "4db242d2aaeaa901d80c55955c53d719", + "entities": [ + { + "tableName": "repository", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `address` TEXT NOT NULL, `mirrors` BLOB NOT NULL, `name` TEXT NOT NULL, `description` TEXT NOT NULL, `version` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `fingerprint` TEXT NOT NULL, `lastModified` TEXT NOT NULL, `entryLastModified` TEXT NOT NULL DEFAULT '', `entityTag` TEXT NOT NULL, `entryEntityTag` TEXT NOT NULL DEFAULT '', `updated` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `authentication` TEXT NOT NULL, `webBaseUrl` TEXT NOT NULL DEFAULT '', `mirrorRotation` INTEGER NOT NULL DEFAULT 0, `trusted` INTEGER NOT NULL DEFAULT 0)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mirrors", + "columnName": "mirrors", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fingerprint", + "columnName": "fingerprint", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastModified", + "columnName": "lastModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entryLastModified", + "columnName": "entryLastModified", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "entityTag", + "columnName": "entityTag", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entryEntityTag", + "columnName": "entryEntityTag", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "updated", + "columnName": "updated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "authentication", + "columnName": "authentication", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webBaseUrl", + "columnName": "webBaseUrl", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "mirrorRotation", + "columnName": "mirrorRotation", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "trusted", + "columnName": "trusted", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_repository_id", + "unique": true, + "columnNames": [ + "id" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_repository_id` ON `${TABLE_NAME}` (`id`)" + }, + { + "name": "index_repository_enabled", + "unique": false, + "columnNames": [ + "enabled" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_repository_enabled` ON `${TABLE_NAME}` (`enabled`)" + }, + { + "name": "index_repository_address", + "unique": false, + "columnNames": [ + "address" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_repository_address` ON `${TABLE_NAME}` (`address`)" + }, + { + "name": "index_repository_updated_enabled", + "unique": false, + "columnNames": [ + "updated", + "enabled" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_repository_updated_enabled` ON `${TABLE_NAME}` (`updated`, `enabled`)" + } + ] + }, + { + "tableName": "product_v2", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `packageName` TEXT NOT NULL, `label` TEXT NOT NULL, `summary` TEXT NOT NULL, `description` TEXT NOT NULL, `added` INTEGER NOT NULL, `updated` INTEGER NOT NULL, `icon` TEXT NOT NULL, `metadataIcon` TEXT NOT NULL, `categories` BLOB NOT NULL, `antiFeatures` BLOB NOT NULL, `licenses` BLOB NOT NULL, `donates` BLOB NOT NULL, `screenshots` BLOB NOT NULL, `suggestedVersionCode` INTEGER NOT NULL, `author` BLOB NOT NULL, `source` TEXT NOT NULL, `web` TEXT NOT NULL, `video` TEXT NOT NULL, `tracker` TEXT NOT NULL, `translation` TEXT NOT NULL DEFAULT '', `changelog` TEXT NOT NULL, `whatsNew` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `packageName`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "summary", + "columnName": "summary", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "added", + "columnName": "added", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updated", + "columnName": "updated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "metadataIcon", + "columnName": "metadataIcon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "categories", + "columnName": "categories", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "antiFeatures", + "columnName": "antiFeatures", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "licenses", + "columnName": "licenses", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "donates", + "columnName": "donates", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "screenshots", + "columnName": "screenshots", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "suggestedVersionCode", + "columnName": "suggestedVersionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "source", + "columnName": "source", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "web", + "columnName": "web", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "video", + "columnName": "video", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tracker", + "columnName": "tracker", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translation", + "columnName": "translation", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "changelog", + "columnName": "changelog", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "whatsNew", + "columnName": "whatsNew", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "packageName" + ] + }, + "indices": [ + { + "name": "index_product_v2_packageName", + "unique": false, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_product_v2_packageName` ON `${TABLE_NAME}` (`packageName`)" + }, + { + "name": "index_product_v2_repositoryId_packageName", + "unique": true, + "columnNames": [ + "repositoryId", + "packageName" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_product_v2_repositoryId_packageName` ON `${TABLE_NAME}` (`repositoryId`, `packageName`)" + }, + { + "name": "index_product_v2_label", + "unique": false, + "columnNames": [ + "label" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_product_v2_label` ON `${TABLE_NAME}` (`label`)" + }, + { + "name": "index_product_v2_added", + "unique": false, + "columnNames": [ + "added" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_product_v2_added` ON `${TABLE_NAME}` (`added`)" + }, + { + "name": "index_product_v2_updated", + "unique": false, + "columnNames": [ + "updated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_product_v2_updated` ON `${TABLE_NAME}` (`updated`)" + }, + { + "name": "index_product_v2_author", + "unique": false, + "columnNames": [ + "author" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_product_v2_author` ON `${TABLE_NAME}` (`author`)" + }, + { + "name": "index_product_v2_packageName_icon_metadataIcon", + "unique": false, + "columnNames": [ + "packageName", + "icon", + "metadataIcon" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_product_v2_packageName_icon_metadataIcon` ON `${TABLE_NAME}` (`packageName`, `icon`, `metadataIcon`)" + }, + { + "name": "index_product_v2_licenses", + "unique": false, + "columnNames": [ + "licenses" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_product_v2_licenses` ON `${TABLE_NAME}` (`licenses`)" + } + ] + }, + { + "tableName": "release", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `repositoryId` INTEGER NOT NULL DEFAULT 0, `selected` INTEGER NOT NULL, `version` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `added` INTEGER NOT NULL, `size` INTEGER NOT NULL, `minSdkVersion` INTEGER NOT NULL, `targetSdkVersion` INTEGER NOT NULL, `maxSdkVersion` INTEGER NOT NULL, `source` TEXT NOT NULL, `release` TEXT NOT NULL, `hash` TEXT NOT NULL, `hashType` TEXT NOT NULL, `signature` TEXT NOT NULL, `obbMain` TEXT NOT NULL, `obbMainHash` TEXT NOT NULL, `obbMainHashType` TEXT NOT NULL, `obbPatch` TEXT NOT NULL, `obbPatchHash` TEXT NOT NULL, `obbPatchHashType` TEXT NOT NULL, `permissions` BLOB NOT NULL, `features` BLOB NOT NULL, `platforms` BLOB NOT NULL, `incompatibilities` BLOB NOT NULL, `isCompatible` INTEGER NOT NULL DEFAULT 0, `releaseChannels` BLOB NOT NULL DEFAULT [], `isStable` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`packageName`, `repositoryId`, `versionCode`, `signature`, `platforms`, `hash`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "selected", + "columnName": "selected", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "added", + "columnName": "added", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "minSdkVersion", + "columnName": "minSdkVersion", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "targetSdkVersion", + "columnName": "targetSdkVersion", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "maxSdkVersion", + "columnName": "maxSdkVersion", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "source", + "columnName": "source", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "release", + "columnName": "release", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hashType", + "columnName": "hashType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "signature", + "columnName": "signature", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbMain", + "columnName": "obbMain", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbMainHash", + "columnName": "obbMainHash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbMainHashType", + "columnName": "obbMainHashType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbPatch", + "columnName": "obbPatch", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbPatchHash", + "columnName": "obbPatchHash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbPatchHashType", + "columnName": "obbPatchHashType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "permissions", + "columnName": "permissions", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "features", + "columnName": "features", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "platforms", + "columnName": "platforms", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "incompatibilities", + "columnName": "incompatibilities", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "isCompatible", + "columnName": "isCompatible", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "releaseChannels", + "columnName": "releaseChannels", + "affinity": "BLOB", + "notNull": true, + "defaultValue": "[]" + }, + { + "fieldPath": "isStable", + "columnName": "isStable", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName", + "repositoryId", + "versionCode", + "signature", + "platforms", + "hash" + ] + }, + "indices": [ + { + "name": "index_release_packageName_repositoryId_versionCode_signature_platforms_hash", + "unique": true, + "columnNames": [ + "packageName", + "repositoryId", + "versionCode", + "signature", + "platforms", + "hash" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_release_packageName_repositoryId_versionCode_signature_platforms_hash` ON `${TABLE_NAME}` (`packageName`, `repositoryId`, `versionCode`, `signature`, `platforms`, `hash`)" + }, + { + "name": "index_release_packageName_minSdkVersion_targetSdkVersion", + "unique": false, + "columnNames": [ + "packageName", + "minSdkVersion", + "targetSdkVersion" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_release_packageName_minSdkVersion_targetSdkVersion` ON `${TABLE_NAME}` (`packageName`, `minSdkVersion`, `targetSdkVersion`)" + }, + { + "name": "index_release_packageName", + "unique": false, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_release_packageName` ON `${TABLE_NAME}` (`packageName`)" + }, + { + "name": "index_release_minSdkVersion", + "unique": false, + "columnNames": [ + "minSdkVersion" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_release_minSdkVersion` ON `${TABLE_NAME}` (`minSdkVersion`)" + }, + { + "name": "index_release_targetSdkVersion", + "unique": false, + "columnNames": [ + "targetSdkVersion" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_release_targetSdkVersion` ON `${TABLE_NAME}` (`targetSdkVersion`)" + }, + { + "name": "index_release_packageName_signature", + "unique": false, + "columnNames": [ + "packageName", + "signature" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_release_packageName_signature` ON `${TABLE_NAME}` (`packageName`, `signature`)" + }, + { + "name": "index_release_repositoryId", + "unique": false, + "columnNames": [ + "repositoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_release_repositoryId` ON `${TABLE_NAME}` (`repositoryId`)" + } + ] + }, + { + "tableName": "temporary_release", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `repositoryId` INTEGER NOT NULL DEFAULT 0, `selected` INTEGER NOT NULL, `version` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `added` INTEGER NOT NULL, `size` INTEGER NOT NULL, `minSdkVersion` INTEGER NOT NULL, `targetSdkVersion` INTEGER NOT NULL, `maxSdkVersion` INTEGER NOT NULL, `source` TEXT NOT NULL, `release` TEXT NOT NULL, `hash` TEXT NOT NULL, `hashType` TEXT NOT NULL, `signature` TEXT NOT NULL, `obbMain` TEXT NOT NULL, `obbMainHash` TEXT NOT NULL, `obbMainHashType` TEXT NOT NULL, `obbPatch` TEXT NOT NULL, `obbPatchHash` TEXT NOT NULL, `obbPatchHashType` TEXT NOT NULL, `permissions` BLOB NOT NULL, `features` BLOB NOT NULL, `platforms` BLOB NOT NULL, `incompatibilities` BLOB NOT NULL, `isCompatible` INTEGER NOT NULL DEFAULT 0, `releaseChannels` BLOB NOT NULL DEFAULT [], `isStable` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`packageName`, `repositoryId`, `versionCode`, `signature`, `platforms`, `hash`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "selected", + "columnName": "selected", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "added", + "columnName": "added", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "minSdkVersion", + "columnName": "minSdkVersion", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "targetSdkVersion", + "columnName": "targetSdkVersion", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "maxSdkVersion", + "columnName": "maxSdkVersion", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "source", + "columnName": "source", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "release", + "columnName": "release", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hashType", + "columnName": "hashType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "signature", + "columnName": "signature", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbMain", + "columnName": "obbMain", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbMainHash", + "columnName": "obbMainHash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbMainHashType", + "columnName": "obbMainHashType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbPatch", + "columnName": "obbPatch", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbPatchHash", + "columnName": "obbPatchHash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "obbPatchHashType", + "columnName": "obbPatchHashType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "permissions", + "columnName": "permissions", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "features", + "columnName": "features", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "platforms", + "columnName": "platforms", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "incompatibilities", + "columnName": "incompatibilities", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "isCompatible", + "columnName": "isCompatible", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "releaseChannels", + "columnName": "releaseChannels", + "affinity": "BLOB", + "notNull": true, + "defaultValue": "[]" + }, + { + "fieldPath": "isStable", + "columnName": "isStable", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName", + "repositoryId", + "versionCode", + "signature", + "platforms", + "hash" + ] + } + }, + { + "tableName": "temporary_product_v2", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `packageName` TEXT NOT NULL, `label` TEXT NOT NULL, `summary` TEXT NOT NULL, `description` TEXT NOT NULL, `added` INTEGER NOT NULL, `updated` INTEGER NOT NULL, `icon` TEXT NOT NULL, `metadataIcon` TEXT NOT NULL, `categories` BLOB NOT NULL, `antiFeatures` BLOB NOT NULL, `licenses` BLOB NOT NULL, `donates` BLOB NOT NULL, `screenshots` BLOB NOT NULL, `suggestedVersionCode` INTEGER NOT NULL, `author` BLOB NOT NULL, `source` TEXT NOT NULL, `web` TEXT NOT NULL, `video` TEXT NOT NULL, `tracker` TEXT NOT NULL, `translation` TEXT NOT NULL DEFAULT '', `changelog` TEXT NOT NULL, `whatsNew` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `packageName`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "summary", + "columnName": "summary", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "added", + "columnName": "added", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updated", + "columnName": "updated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "metadataIcon", + "columnName": "metadataIcon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "categories", + "columnName": "categories", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "antiFeatures", + "columnName": "antiFeatures", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "licenses", + "columnName": "licenses", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "donates", + "columnName": "donates", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "screenshots", + "columnName": "screenshots", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "suggestedVersionCode", + "columnName": "suggestedVersionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "source", + "columnName": "source", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "web", + "columnName": "web", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "video", + "columnName": "video", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tracker", + "columnName": "tracker", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translation", + "columnName": "translation", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "changelog", + "columnName": "changelog", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "whatsNew", + "columnName": "whatsNew", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "packageName" + ] + } + }, + { + "tableName": "category_v2", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `packageName` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `packageName`, `name`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "packageName", + "name" + ] + }, + "indices": [ + { + "name": "index_category_v2_repositoryId_packageName_name", + "unique": true, + "columnNames": [ + "repositoryId", + "packageName", + "name" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_category_v2_repositoryId_packageName_name` ON `${TABLE_NAME}` (`repositoryId`, `packageName`, `name`)" + }, + { + "name": "index_category_v2_packageName_name", + "unique": false, + "columnNames": [ + "packageName", + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_category_v2_packageName_name` ON `${TABLE_NAME}` (`packageName`, `name`)" + }, + { + "name": "index_category_v2_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_category_v2_name` ON `${TABLE_NAME}` (`name`)" + }, + { + "name": "index_category_v2_repositoryId", + "unique": false, + "columnNames": [ + "repositoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_category_v2_repositoryId` ON `${TABLE_NAME}` (`repositoryId`)" + } + ] + }, + { + "tableName": "temporary_category_v2", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `packageName` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `packageName`, `name`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "packageName", + "name" + ] + } + }, + { + "tableName": "repo_category", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `name` TEXT NOT NULL, `label` TEXT NOT NULL, `icon` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `name`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "name" + ] + }, + "indices": [ + { + "name": "index_repo_category_repositoryId_name", + "unique": true, + "columnNames": [ + "repositoryId", + "name" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_repo_category_repositoryId_name` ON `${TABLE_NAME}` (`repositoryId`, `name`)" + }, + { + "name": "index_repo_category_name_label", + "unique": false, + "columnNames": [ + "name", + "label" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_repo_category_name_label` ON `${TABLE_NAME}` (`name`, `label`)" + }, + { + "name": "index_repo_category_name_label_icon", + "unique": false, + "columnNames": [ + "name", + "label", + "icon" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_repo_category_name_label_icon` ON `${TABLE_NAME}` (`name`, `label`, `icon`)" + }, + { + "name": "index_repo_category_repositoryId", + "unique": false, + "columnNames": [ + "repositoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_repo_category_repositoryId` ON `${TABLE_NAME}` (`repositoryId`)" + }, + { + "name": "index_repo_category_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_repo_category_name` ON `${TABLE_NAME}` (`name`)" + } + ] + }, + { + "tableName": "temporary_repo_category", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `name` TEXT NOT NULL, `label` TEXT NOT NULL, `icon` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `name`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "name" + ] + } + }, + { + "tableName": "memory_installed", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `version` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `signatures` BLOB NOT NULL DEFAULT [], `isSystem` INTEGER NOT NULL, `isEnabled` INTEGER NOT NULL DEFAULT 1, `launcherActivities` BLOB NOT NULL, PRIMARY KEY(`packageName`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "signatures", + "columnName": "signatures", + "affinity": "BLOB", + "notNull": true, + "defaultValue": "[]" + }, + { + "fieldPath": "isSystem", + "columnName": "isSystem", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isEnabled", + "columnName": "isEnabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "launcherActivities", + "columnName": "launcherActivities", + "affinity": "BLOB", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName" + ] + }, + "indices": [ + { + "name": "index_memory_installed_packageName", + "unique": true, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_memory_installed_packageName` ON `${TABLE_NAME}` (`packageName`)" + } + ] + }, + { + "tableName": "extras", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `favorite` INTEGER NOT NULL, `ignoreUpdates` INTEGER NOT NULL, `ignoredVersion` INTEGER NOT NULL, `ignoreVulns` INTEGER NOT NULL DEFAULT 0, `allowUnstable` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`packageName`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "favorite", + "columnName": "favorite", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ignoreUpdates", + "columnName": "ignoreUpdates", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ignoredVersion", + "columnName": "ignoredVersion", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ignoreVulns", + "columnName": "ignoreVulns", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "allowUnstable", + "columnName": "allowUnstable", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName" + ] + }, + "indices": [ + { + "name": "index_extras_packageName", + "unique": true, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_extras_packageName` ON `${TABLE_NAME}` (`packageName`)" + }, + { + "name": "index_extras_favorite", + "unique": false, + "columnNames": [ + "favorite" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extras_favorite` ON `${TABLE_NAME}` (`favorite`)" + }, + { + "name": "index_extras_ignoreVulns", + "unique": false, + "columnNames": [ + "ignoreVulns" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extras_ignoreVulns` ON `${TABLE_NAME}` (`ignoreVulns`)" + }, + { + "name": "index_extras_ignoreUpdates", + "unique": false, + "columnNames": [ + "ignoreUpdates" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extras_ignoreUpdates` ON `${TABLE_NAME}` (`ignoreUpdates`)" + }, + { + "name": "index_extras_ignoredVersion", + "unique": false, + "columnNames": [ + "ignoredVersion" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extras_ignoredVersion` ON `${TABLE_NAME}` (`ignoredVersion`)" + }, + { + "name": "index_extras_allowUnstable", + "unique": false, + "columnNames": [ + "allowUnstable" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_extras_allowUnstable` ON `${TABLE_NAME}` (`allowUnstable`)" + } + ] + }, + { + "tableName": "exodus_info", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `handle` TEXT NOT NULL, `app_name` TEXT NOT NULL, `uaid` TEXT NOT NULL, `version_name` TEXT NOT NULL, `version_code` TEXT NOT NULL, `source` TEXT NOT NULL, `icon_hash` TEXT NOT NULL, `apk_hash` TEXT NOT NULL, `created` TEXT NOT NULL, `updated` TEXT NOT NULL, `report` INTEGER NOT NULL, `creator` TEXT NOT NULL, `downloads` TEXT NOT NULL, `trackers` BLOB NOT NULL, `permissions` BLOB NOT NULL, PRIMARY KEY(`packageName`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "handle", + "columnName": "handle", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "app_name", + "columnName": "app_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "uaid", + "columnName": "uaid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version_name", + "columnName": "version_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version_code", + "columnName": "version_code", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "source", + "columnName": "source", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon_hash", + "columnName": "icon_hash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "apk_hash", + "columnName": "apk_hash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "created", + "columnName": "created", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "updated", + "columnName": "updated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "report", + "columnName": "report", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "creator", + "columnName": "creator", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "downloads", + "columnName": "downloads", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "trackers", + "columnName": "trackers", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "permissions", + "columnName": "permissions", + "affinity": "BLOB", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName" + ] + }, + "indices": [ + { + "name": "index_exodus_info_packageName", + "unique": false, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_exodus_info_packageName` ON `${TABLE_NAME}` (`packageName`)" + } + ] + }, + { + "tableName": "tracker", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` INTEGER NOT NULL, `name` TEXT NOT NULL, `network_signature` TEXT NOT NULL, `code_signature` TEXT NOT NULL, `creation_date` TEXT NOT NULL, `website` TEXT NOT NULL, `description` TEXT NOT NULL, `categories` BLOB NOT NULL, `documentation` BLOB NOT NULL, PRIMARY KEY(`key`))", + "fields": [ + { + "fieldPath": "key", + "columnName": "key", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "network_signature", + "columnName": "network_signature", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "code_signature", + "columnName": "code_signature", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "creation_date", + "columnName": "creation_date", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "website", + "columnName": "website", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "categories", + "columnName": "categories", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "documentation", + "columnName": "documentation", + "affinity": "BLOB", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "key" + ] + }, + "indices": [ + { + "name": "index_tracker_key", + "unique": true, + "columnNames": [ + "key" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_tracker_key` ON `${TABLE_NAME}` (`key`)" + } + ] + }, + { + "tableName": "downloaded", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `label` TEXT NOT NULL DEFAULT '', `version` TEXT NOT NULL, `repositoryId` INTEGER NOT NULL DEFAULT 0, `cacheFileName` TEXT NOT NULL, `changed` INTEGER NOT NULL, `state` BLOB NOT NULL, PRIMARY KEY(`packageName`, `version`, `cacheFileName`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "cacheFileName", + "columnName": "cacheFileName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "changed", + "columnName": "changed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "BLOB", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName", + "version", + "cacheFileName" + ] + }, + "indices": [ + { + "name": "index_downloaded_packageName_version_cacheFileName", + "unique": true, + "columnNames": [ + "packageName", + "version", + "cacheFileName" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_downloaded_packageName_version_cacheFileName` ON `${TABLE_NAME}` (`packageName`, `version`, `cacheFileName`)" + }, + { + "name": "index_downloaded_packageName", + "unique": false, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_downloaded_packageName` ON `${TABLE_NAME}` (`packageName`)" + }, + { + "name": "index_downloaded_changed", + "unique": false, + "columnNames": [ + "changed" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_downloaded_changed` ON `${TABLE_NAME}` (`changed`)" + } + ] + }, + { + "tableName": "install_task", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `repositoryId` INTEGER NOT NULL, `versionCode` INTEGER NOT NULL, `versionName` TEXT NOT NULL, `label` TEXT NOT NULL, `cacheFileName` TEXT NOT NULL, `added` INTEGER NOT NULL, `requireUser` INTEGER NOT NULL, PRIMARY KEY(`packageName`, `repositoryId`, `versionCode`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "versionName", + "columnName": "versionName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "cacheFileName", + "columnName": "cacheFileName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "added", + "columnName": "added", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "requireUser", + "columnName": "requireUser", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName", + "repositoryId", + "versionCode" + ] + }, + "indices": [ + { + "name": "index_install_task_packageName_repositoryId_versionCode", + "unique": true, + "columnNames": [ + "packageName", + "repositoryId", + "versionCode" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_install_task_packageName_repositoryId_versionCode` ON `${TABLE_NAME}` (`packageName`, `repositoryId`, `versionCode`)" + }, + { + "name": "index_install_task_packageName", + "unique": false, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_install_task_packageName` ON `${TABLE_NAME}` (`packageName`)" + }, + { + "name": "index_install_task_added", + "unique": false, + "columnNames": [ + "added" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_install_task_added` ON `${TABLE_NAME}` (`added`)" + }, + { + "name": "index_install_task_cacheFileName", + "unique": false, + "columnNames": [ + "cacheFileName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_install_task_cacheFileName` ON `${TABLE_NAME}` (`cacheFileName`)" + } + ] + }, + { + "tableName": "antifeature", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `name` TEXT NOT NULL, `label` TEXT NOT NULL, `description` TEXT NOT NULL, `icon` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `name`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "name" + ] + }, + "indices": [ + { + "name": "index_antifeature_name_label", + "unique": false, + "columnNames": [ + "name", + "label" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_antifeature_name_label` ON `${TABLE_NAME}` (`name`, `label`)" + }, + { + "name": "index_antifeature_name_label_description_icon", + "unique": false, + "columnNames": [ + "name", + "label", + "description", + "icon" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_antifeature_name_label_description_icon` ON `${TABLE_NAME}` (`name`, `label`, `description`, `icon`)" + }, + { + "name": "index_antifeature_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_antifeature_name` ON `${TABLE_NAME}` (`name`)" + }, + { + "name": "index_antifeature_repositoryId", + "unique": false, + "columnNames": [ + "repositoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_antifeature_repositoryId` ON `${TABLE_NAME}` (`repositoryId`)" + } + ] + }, + { + "tableName": "temporary_antifeature", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repositoryId` INTEGER NOT NULL, `name` TEXT NOT NULL, `label` TEXT NOT NULL, `description` TEXT NOT NULL, `icon` TEXT NOT NULL, PRIMARY KEY(`repositoryId`, `name`))", + "fields": [ + { + "fieldPath": "repositoryId", + "columnName": "repositoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repositoryId", + "name" + ] + } + }, + { + "tableName": "rb_log", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`hash` TEXT NOT NULL, `repository` TEXT NOT NULL, `apk_url` TEXT NOT NULL, `packageName` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `versionName` TEXT NOT NULL, `tag` TEXT NOT NULL, `commit` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `reproducible` INTEGER, `error` TEXT, PRIMARY KEY(`hash`, `packageName`, `timestamp`))", + "fields": [ + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repository", + "columnName": "repository", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "apk_url", + "columnName": "apk_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "appid", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version_code", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version_name", + "columnName": "versionName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tag", + "columnName": "tag", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "commit", + "columnName": "commit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reproducible", + "columnName": "reproducible", + "affinity": "INTEGER" + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "hash", + "packageName", + "timestamp" + ] + }, + "indices": [ + { + "name": "index_rb_log_hash_packageName_timestamp", + "unique": true, + "columnNames": [ + "hash", + "packageName", + "timestamp" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_rb_log_hash_packageName_timestamp` ON `${TABLE_NAME}` (`hash`, `packageName`, `timestamp`)" + }, + { + "name": "index_rb_log_packageName_versionCode_reproducible", + "unique": false, + "columnNames": [ + "packageName", + "versionCode", + "reproducible" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_rb_log_packageName_versionCode_reproducible` ON `${TABLE_NAME}` (`packageName`, `versionCode`, `reproducible`)" + }, + { + "name": "index_rb_log_packageName_hash_reproducible", + "unique": false, + "columnNames": [ + "packageName", + "hash", + "reproducible" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_rb_log_packageName_hash_reproducible` ON `${TABLE_NAME}` (`packageName`, `hash`, `reproducible`)" + }, + { + "name": "index_rb_log_packageName", + "unique": false, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_rb_log_packageName` ON `${TABLE_NAME}` (`packageName`)" + } + ] + }, + { + "tableName": "download_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `isoDate` INTEGER NOT NULL, `client` TEXT NOT NULL, `source` TEXT NOT NULL, `count` INTEGER NOT NULL, PRIMARY KEY(`packageName`, `isoDate`, `client`, `source`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "isoDate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "client", + "columnName": "client", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "source", + "columnName": "source", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "count", + "columnName": "count", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName", + "isoDate", + "client", + "source" + ] + }, + "indices": [ + { + "name": "index_download_stats_packageName_isoDate_client_source", + "unique": true, + "columnNames": [ + "packageName", + "isoDate", + "client", + "source" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_download_stats_packageName_isoDate_client_source` ON `${TABLE_NAME}` (`packageName`, `isoDate`, `client`, `source`)" + }, + { + "name": "index_download_stats_packageName_isoDate", + "unique": false, + "columnNames": [ + "packageName", + "isoDate" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_download_stats_packageName_isoDate` ON `${TABLE_NAME}` (`packageName`, `isoDate`)" + }, + { + "name": "index_download_stats_packageName", + "unique": false, + "columnNames": [ + "packageName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_download_stats_packageName` ON `${TABLE_NAME}` (`packageName`)" + }, + { + "name": "index_download_stats_client", + "unique": false, + "columnNames": [ + "client" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_download_stats_client` ON `${TABLE_NAME}` (`client`)" + }, + { + "name": "index_download_stats_isoDate", + "unique": false, + "columnNames": [ + "isoDate" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_download_stats_isoDate` ON `${TABLE_NAME}` (`isoDate`)" + } + ] + }, + { + "tableName": "ds_file_meta_data", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`fileName` TEXT NOT NULL, `lastModified` TEXT NOT NULL, `lastFetched` INTEGER NOT NULL, `fetchSuccess` INTEGER NOT NULL, `fileSize` INTEGER, `recordsCount` INTEGER, PRIMARY KEY(`fileName`))", + "fields": [ + { + "fieldPath": "fileName", + "columnName": "fileName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastModified", + "columnName": "lastModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastFetched", + "columnName": "lastFetched", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fetchSuccess", + "columnName": "fetchSuccess", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fileSize", + "columnName": "fileSize", + "affinity": "INTEGER" + }, + { + "fieldPath": "recordsCount", + "columnName": "recordsCount", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "fileName" + ] + }, + "indices": [ + { + "name": "index_ds_file_meta_data_fileName", + "unique": true, + "columnNames": [ + "fileName" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_ds_file_meta_data_fileName` ON `${TABLE_NAME}` (`fileName`)" + }, + { + "name": "index_ds_file_meta_data_fileName_lastModified", + "unique": false, + "columnNames": [ + "fileName", + "lastModified" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_ds_file_meta_data_fileName_lastModified` ON `${TABLE_NAME}` (`fileName`, `lastModified`)" + } + ] + } + ], + "views": [ + { + "viewName": "PackageSum", + "createSql": "CREATE VIEW `${VIEW_NAME}` AS SELECT packageName AS packageName,\n SUM(count) AS totalCount\n FROM download_stats\n WHERE client = '_total'\n GROUP BY packageName" + }, + { + "viewName": "ClientPackageSum", + "createSql": "CREATE VIEW `${VIEW_NAME}` AS SELECT packageName AS packageName,\n client AS client,\n SUM(count) AS totalCount\n FROM download_stats\n GROUP BY packageName, client" + }, + { + "viewName": "MonthlyPackageSum", + "createSql": "CREATE VIEW `${VIEW_NAME}` AS SELECT packageName AS packageName,\n client AS client,\n (isoDate / 100) AS yearMonth,\n SUM(count) AS totalCount\n FROM download_stats\n GROUP BY packageName, client, yearMonth" + }, + { + "viewName": "ProductIconDetails", + "createSql": "CREATE VIEW `${VIEW_NAME}` AS SELECT mg.packageName AS packageName,\n mg.repositoryId AS repositoryId,\n mg.icon AS icon,\n mg.metadataIcon AS metadataIcon\n FROM product_v2 AS mg\n JOIN (\n SELECT packageName, MAX(updated) AS latest\n FROM product_v2\n GROUP BY packageName\n ) AS sg\n ON mg.packageName = sg.packageName AND mg.updated = sg.latest" + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '4db242d2aaeaa901d80c55955c53d719')" + ] + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/database/DatabaseX.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/database/DatabaseX.kt index 15774f95ba..a3f5666e16 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/database/DatabaseX.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/database/DatabaseX.kt @@ -125,7 +125,7 @@ import java.io.File DownloadStats::class, DownloadStatsFileMetadata::class, ], - version = 1208, + version = 1209, exportSchema = true, views = [ PackageSum::class, @@ -313,6 +313,11 @@ import java.io.File from = 1207, to = 1208, ), + AutoMigration( + from = 1208, + to = 1209, + spec = DatabaseX.Companion.ProductsCleanupKeepDownloaded::class + ), ] ) @TypeConverters(Converters::class) @@ -537,6 +542,22 @@ abstract class DatabaseX : RoomDatabase() { } } + class ProductsCleanupKeepDownloaded : AutoMigrationSpec { + override fun onPostMigrate(db: SupportSQLiteDatabase) { + super.onPostMigrate(db) + GlobalScope.launch(Dispatchers.IO) { + get(DatabaseX::class.java).apply { + withTransaction { + getProductDao().emptyTable() + getCategoryDao().emptyTable() + getReleaseDao().emptyTable() + getRepositoryDao().forgetLastModifications() + } + } + } + } + } + class ProductsCleanup : AutoMigrationSpec { override fun onPostMigrate(db: SupportSQLiteDatabase) { super.onPostMigrate(db) diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/IndexProduct.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/IndexProduct.kt index 45fc285043..e9be1483b5 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/IndexProduct.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/IndexProduct.kt @@ -142,8 +142,7 @@ open class IndexProduct( }.toMutableList() val predicate: (Release) -> Boolean = { - unstable || (!it.releaseChannels.contains("Beta") && suggestedVersionCode <= 0) || - it.versionCode <= suggestedVersionCode + unstable || it.isStable } val firstCompatibleReleaseIndex = releasePairs.indexOfFirst { it.second.isEmpty() && predicate(it.first) } diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Product.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Product.kt index ea39185e06..7c878515d6 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Product.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Product.kt @@ -271,8 +271,7 @@ data class EmbeddedProduct( }.toImmutableList() val predicate: (Release) -> Boolean = { - unstable || (!it.releaseChannels.contains("Beta") && product.suggestedVersionCode <= 0) || - it.versionCode <= product.suggestedVersionCode + unstable || it.isStable } val firstCompatibleReleaseIndex = releasePairs.indexOfFirst { it.second.isEmpty() && predicate(it.first) } @@ -328,4 +327,4 @@ data class ProductIconDetails( val repositoryId: Long, val icon: String, val metadataIcon: String -) \ No newline at end of file +) diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Release.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Release.kt index 31f600cd80..13b77a8100 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Release.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/database/entity/Release.kt @@ -65,6 +65,8 @@ open class Release( val isCompatible: Boolean, @ColumnInfo(defaultValue = "[]") val releaseChannels: List = emptyList(), + @ColumnInfo(defaultValue = "0") + val isStable: Boolean, ) { @Serializable sealed class Incompatibility { @@ -140,6 +142,7 @@ open class Release( incompatibilities = incompatibilities, isCompatible = incompatibilities.isEmpty(), releaseChannels = releaseChannels, + isStable = isStable, ) } @@ -172,6 +175,7 @@ class ReleaseTemp( incompatibilities: List, isCompatible: Boolean, releaseChannels: List, + isStable: Boolean, ) : Release( packageName = packageName, repositoryId = repositoryId, @@ -200,6 +204,7 @@ class ReleaseTemp( incompatibilities = incompatibilities, isCompatible = isCompatible, releaseChannels = releaseChannels, + isStable = isStable, ) fun Release.asReleaseTemp() = ReleaseTemp( @@ -230,4 +235,5 @@ fun Release.asReleaseTemp() = ReleaseTemp( incompatibilities = incompatibilities, isCompatible = isCompatible, releaseChannels = releaseChannels, + isStable = isStable, ) diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v0/IndexV0Parser.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v0/IndexV0Parser.kt index 3db9074edf..96103a404d 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v0/IndexV0Parser.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v0/IndexV0Parser.kt @@ -135,6 +135,7 @@ class IndexV0Parser(private val repositoryId: Long, private val callback: Callba var obbMainHash = "" var obbPatch = "" var obbPatchHash = "" + var isStable = false val permissions = linkedSetOf() val features = linkedSetOf() val platforms = linkedSetOf() @@ -170,6 +171,7 @@ class IndexV0Parser(private val repositoryId: Long, private val callback: Callba platforms = platforms.toList(), incompatibilities = emptyList(), isCompatible = true, + isStable = isStable, ) } } @@ -338,8 +340,11 @@ class IndexV0Parser(private val repositoryId: Long, private val callback: Callba -> releaseBuilder.version = readText() "versioncode" - -> releaseBuilder.versionCode = - readText().toLongOrNull() ?: 0L + -> { + releaseBuilder.versionCode = readText().toLongOrNull() ?: 0L + releaseBuilder.isStable = productBuilder.suggestedVersionCode + .let { it <= 0 || releaseBuilder.versionCode <= it } + } "added" -> releaseBuilder.added = readText().parseDate() diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/Converter.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/Converter.kt index e871912155..f7003c99ab 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/Converter.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/Converter.kt @@ -77,9 +77,9 @@ internal fun IndexV1.App.toProduct(repositoryId: Long) = IndexProduct( internal fun IndexV1.Package.toRelease( repositoryId: Long, - packageName: String + product: IndexV1.App ) = Release( - packageName = packageName, + packageName = product.packageName, repositoryId = repositoryId, selected = false, version = versionName, @@ -112,6 +112,8 @@ internal fun IndexV1.Package.toRelease( platforms = nativecode, incompatibilities = emptyList(), isCompatible = true, + isStable = product.suggestedVersionCode.toLongOrDefault(0L) + .let { it <= 0 || versionCode <= it }, ) internal fun Map.findLocalizedString( @@ -204,4 +206,4 @@ private fun Map.getAndCall( callback: (String, IndexV1.Localized) -> T?, ): T? { return this[key]?.let { callback(key, it) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/IndexV1Parser.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/IndexV1Parser.kt index 4380b820d7..b343b869ea 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/IndexV1Parser.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v1/IndexV1Parser.kt @@ -29,13 +29,13 @@ class IndexV1Parser(private val repositoryId: Long, private val callback: Callba indexV1.apps.forEach { product -> callback.onProduct(product.toProduct(repositoryId)) - } - indexV1.packages.forEach { (packageName, releases) -> - callback.onReleases( - packageName, - releases.map { it.toRelease(repositoryId, packageName) }, - ) + indexV1.packages[product.packageName]?.let { releases -> + callback.onReleases( + product.packageName, + releases.map { it.toRelease(repositoryId, product) }, + ) + } } } catch (e: Exception) { throw ParsingException("Error parsing index", e) diff --git a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v2/Converter.kt b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v2/Converter.kt index 28408fc35d..6a13cc157a 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/data/index/v2/Converter.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/data/index/v2/Converter.kt @@ -102,6 +102,7 @@ internal fun IndexV2.Version.toRelease( incompatibilities = emptyList(), isCompatible = true, releaseChannels = releaseChannels, + isStable = releaseChannels.isEmpty(), ) internal fun Localized?.findLocalized(fallback: T): T = diff --git a/src/main/kotlin/com/machiav3lli/fdroid/ui/pages/PrefsOtherPage.kt b/src/main/kotlin/com/machiav3lli/fdroid/ui/pages/PrefsOtherPage.kt index b939bc95c5..2c02d00771 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/ui/pages/PrefsOtherPage.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/ui/pages/PrefsOtherPage.kt @@ -44,7 +44,6 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.net.toUri import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.machiav3lli.fdroid.BuildConfig -import com.machiav3lli.fdroid.NeoApp import com.machiav3lli.fdroid.R import com.machiav3lli.fdroid.data.content.Preferences import com.machiav3lli.fdroid.data.content.SAFFile @@ -57,6 +56,7 @@ import com.machiav3lli.fdroid.ui.components.prefs.BasePreference import com.machiav3lli.fdroid.ui.components.prefs.PreferenceGroup import com.machiav3lli.fdroid.ui.compose.icons.Phosphor import com.machiav3lli.fdroid.ui.compose.icons.phosphor.CircleWavyWarning +import com.machiav3lli.fdroid.utils.Utils.startUpdate import com.machiav3lli.fdroid.utils.currentTimestamp import com.machiav3lli.fdroid.utils.extension.koinNeoViewModel import com.machiav3lli.fdroid.utils.isDefaultAppHandler @@ -169,17 +169,19 @@ fun PrefsOtherPage( Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) + val repos = pageState.repos.associateBy { it.id } SAFFile(context, resultUri).read() ?.split(">") ?.filterNot { pageState.installedMap.keys.contains(it) } ?.forEach { packageName -> scope.launch(Dispatchers.IO) { - productRepo.loadProduct(packageName) - .maxByOrNull { it.product.suggestedVersionCode }?.toItem()?.let { - NeoApp.wm.install( - Pair(it.packageName, it.repositoryId) - ) - } + startUpdate( + packageName, + null, + productRepo.loadProduct(packageName).mapNotNull { ep -> + repos[ep.product.repositoryId]?.let { Pair(ep, it) } + }, + ) } } // TODO add notification about success or failure diff --git a/src/main/kotlin/com/machiav3lli/fdroid/utils/Utils.kt b/src/main/kotlin/com/machiav3lli/fdroid/utils/Utils.kt index a57367d793..e365d88682 100644 --- a/src/main/kotlin/com/machiav3lli/fdroid/utils/Utils.kt +++ b/src/main/kotlin/com/machiav3lli/fdroid/utils/Utils.kt @@ -146,7 +146,7 @@ object Utils { } private fun List.getBestRelease(installedVersionCode: Long): Release? { - filter { it.versionCode > installedVersionCode } + filter { it.versionCode > installedVersionCode && (Preferences[Preferences.Key.UpdateUnstable] || it.isStable) } .apply { if (isEmpty()) return null if (size == 1) return first()