diff --git a/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json b/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json index 041d1dea..0fb6425d 100644 --- a/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json +++ b/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "371c7a84b122a2de8b660b35e6e9ce14", + "identityHash": "802fa2fda94b930bf0ebb85d195f1022", "entities": [ { "tableName": "patch_bundles", @@ -295,12 +295,119 @@ ] } ] + }, + { + "tableName": "option_groups", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `patch_bundle` INTEGER NOT NULL, `package_name` TEXT NOT NULL, PRIMARY KEY(`uid`), FOREIGN KEY(`patch_bundle`) REFERENCES `patch_bundles`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "uid", + "columnName": "uid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "patchBundle", + "columnName": "patch_bundle", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "package_name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "uid" + ] + }, + "indices": [ + { + "name": "index_option_groups_patch_bundle_package_name", + "unique": true, + "columnNames": [ + "patch_bundle", + "package_name" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_option_groups_patch_bundle_package_name` ON `${TABLE_NAME}` (`patch_bundle`, `package_name`)" + } + ], + "foreignKeys": [ + { + "table": "patch_bundles", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "patch_bundle" + ], + "referencedColumns": [ + "uid" + ] + } + ] + }, + { + "tableName": "options", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`group` INTEGER NOT NULL, `patch_name` TEXT NOT NULL, `key` TEXT NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY(`group`, `patch_name`, `key`), FOREIGN KEY(`group`) REFERENCES `option_groups`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "group", + "columnName": "group", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "patchName", + "columnName": "patch_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "group", + "patch_name", + "key" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "option_groups", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "group" + ], + "referencedColumns": [ + "uid" + ] + } + ] } ], "views": [], "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, '371c7a84b122a2de8b660b35e6e9ce14')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '802fa2fda94b930bf0ebb85d195f1022')" ] } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt b/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt index e1a0f81b..0440a7c2 100644 --- a/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt +++ b/app/src/main/java/app/revanced/manager/data/room/AppDatabase.kt @@ -13,15 +13,19 @@ import app.revanced.manager.data.room.selection.SelectedPatch import app.revanced.manager.data.room.selection.SelectionDao import app.revanced.manager.data.room.bundles.PatchBundleDao import app.revanced.manager.data.room.bundles.PatchBundleEntity +import app.revanced.manager.data.room.options.Option +import app.revanced.manager.data.room.options.OptionDao +import app.revanced.manager.data.room.options.OptionGroup import kotlin.random.Random -@Database(entities = [PatchBundleEntity::class, PatchSelection::class, SelectedPatch::class, DownloadedApp::class, InstalledApp::class, AppliedPatch::class], version = 1) +@Database(entities = [PatchBundleEntity::class, PatchSelection::class, SelectedPatch::class, DownloadedApp::class, InstalledApp::class, AppliedPatch::class, OptionGroup::class, Option::class], version = 1) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun patchBundleDao(): PatchBundleDao abstract fun selectionDao(): SelectionDao abstract fun downloadedAppDao(): DownloadedAppDao abstract fun installedAppDao(): InstalledAppDao + abstract fun optionDao(): OptionDao companion object { fun generateUid() = Random.Default.nextInt() diff --git a/app/src/main/java/app/revanced/manager/data/room/options/Option.kt b/app/src/main/java/app/revanced/manager/data/room/options/Option.kt new file mode 100644 index 00000000..3a70a9a5 --- /dev/null +++ b/app/src/main/java/app/revanced/manager/data/room/options/Option.kt @@ -0,0 +1,23 @@ +package app.revanced.manager.data.room.options + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.ForeignKey + +@Entity( + tableName = "options", + primaryKeys = ["group", "patch_name", "key"], + foreignKeys = [ForeignKey( + OptionGroup::class, + parentColumns = ["uid"], + childColumns = ["group"], + onDelete = ForeignKey.CASCADE + )] +) +data class Option( + @ColumnInfo(name = "group") val group: Int, + @ColumnInfo(name = "patch_name") val patchName: String, + @ColumnInfo(name = "key") val key: String, + // Encoded as Json. + @ColumnInfo(name = "value") val value: String, +) \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/data/room/options/OptionDao.kt b/app/src/main/java/app/revanced/manager/data/room/options/OptionDao.kt new file mode 100644 index 00000000..fa343a6d --- /dev/null +++ b/app/src/main/java/app/revanced/manager/data/room/options/OptionDao.kt @@ -0,0 +1,51 @@ +package app.revanced.manager.data.room.options + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.MapInfo +import androidx.room.Query +import androidx.room.Transaction +import kotlinx.coroutines.flow.Flow + +@Dao +abstract class OptionDao { + @Transaction + @MapInfo(keyColumn = "patch_bundle") + @Query( + "SELECT patch_bundle, `group`, patch_name, `key`, value FROM option_groups" + + " LEFT JOIN options ON uid = options.`group`" + + " WHERE package_name = :packageName" + ) + abstract suspend fun getOptions(packageName: String): Map> + + @Query("SELECT uid FROM option_groups WHERE patch_bundle = :bundleUid AND package_name = :packageName") + abstract suspend fun getGroupId(bundleUid: Int, packageName: String): Int? + + @Query("SELECT package_name FROM option_groups") + abstract fun getPackagesWithOptions(): Flow> + + @Insert + abstract suspend fun createOptionGroup(group: OptionGroup) + + @Query("DELETE FROM option_groups WHERE patch_bundle = :uid") + abstract suspend fun clearForPatchBundle(uid: Int) + + @Query("DELETE FROM option_groups WHERE package_name = :packageName") + abstract suspend fun clearForPackage(packageName: String) + + @Query("DELETE FROM option_groups") + abstract suspend fun reset() + + @Insert + protected abstract suspend fun insertOptions(patches: List