From b05e5b9cd074431930422d5181b3d3e08c03f8d7 Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Tue, 11 Jun 2024 16:51:16 +0800 Subject: [PATCH] Optimize `database` - Optimize `ModulesJson` - Remove `model.state` --- .../1.json | 309 ++++++++++++++++++ .../dev/sanmer/mrepo/database/AppDatabase.kt | 166 +--------- .../dev/sanmer/mrepo/database/dao/JoinDao.kt | 31 +- .../dev/sanmer/mrepo/database/dao/LocalDao.kt | 19 +- .../sanmer/mrepo/database/dao/OnlineDao.kt | 4 +- .../dev/sanmer/mrepo/database/dao/RepoDao.kt | 18 +- .../sanmer/mrepo/database/dao/VersionDao.kt | 2 +- .../dev/sanmer/mrepo/database/entity/Local.kt | 14 +- .../sanmer/mrepo/database/entity/Online.kt | 66 ++-- .../dev/sanmer/mrepo/database/entity/Repo.kt | 38 +-- .../sanmer/mrepo/database/entity/Version.kt | 5 +- .../sanmer/mrepo/model/online/ModulesJson.kt | 26 +- .../sanmer/mrepo/model/online/OnlineModule.kt | 4 +- .../sanmer/mrepo/model/online/TrackJson.kt | 27 +- .../sanmer/mrepo/model/online/VersionItem.kt | 4 +- .../sanmer/mrepo/model/state/OnlineState.kt | 42 --- .../dev/sanmer/mrepo/model/state/RepoState.kt | 37 --- .../mrepo/repository/LocalRepository.kt | 33 +- .../mrepo/repository/ModulesRepository.kt | 4 +- .../sanmer/mrepo/ui/activity/MainActivity.kt | 2 +- .../mrepo/ui/screens/modules/ModuleItem.kt | 13 +- .../mrepo/ui/screens/repository/ModuleItem.kt | 2 +- .../ui/screens/repository/ModulesList.kt | 2 +- .../ui/screens/repository/RepositoryMenu.kt | 2 +- .../ui/screens/repository/view/ViewTopBar.kt | 6 +- .../repository/view/items/TrackItem.kt | 6 +- .../repository/view/pages/OverviewPage.kt | 9 +- .../repository/view/pages/VersionsPage.kt | 6 +- .../settings/repositories/RepositoriesList.kt | 2 +- .../settings/repositories/RepositoryItem.kt | 19 +- .../sanmer/mrepo/viewmodel/ModuleViewModel.kt | 8 +- .../mrepo/viewmodel/RepositoriesViewModel.kt | 32 +- .../mrepo/viewmodel/RepositoryViewModel.kt | 44 ++- 33 files changed, 567 insertions(+), 435 deletions(-) create mode 100644 app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/model/state/OnlineState.kt delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/model/state/RepoState.kt diff --git a/app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json b/app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json new file mode 100644 index 00000000..45686ecd --- /dev/null +++ b/app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json @@ -0,0 +1,309 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "b1bfea045a8aae2b31e57dcfb1f9a45c", + "entities": [ + { + "tableName": "repo", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `name` TEXT NOT NULL, `enable` INTEGER NOT NULL, `timestamp` REAL NOT NULL, `size` INTEGER NOT NULL, PRIMARY KEY(`url`))", + "fields": [ + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "enable", + "columnName": "enable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "metadata.timestamp", + "columnName": "timestamp", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "metadata.size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "url" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "local_updatable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `updatable` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "updatable", + "columnName": "updatable", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "online", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `repoUrl` TEXT NOT NULL, `name` TEXT NOT NULL, `version` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `author` TEXT NOT NULL, `description` TEXT NOT NULL, `type` TEXT NOT NULL, `added` REAL NOT NULL, `license` TEXT NOT NULL, `homepage` TEXT NOT NULL, `source` TEXT NOT NULL, `support` TEXT NOT NULL, `donate` TEXT NOT NULL, PRIMARY KEY(`id`, `repoUrl`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoUrl", + "columnName": "repoUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "track.type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "track.added", + "columnName": "added", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "track.license", + "columnName": "license", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "track.homepage", + "columnName": "homepage", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "track.source", + "columnName": "source", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "track.support", + "columnName": "support", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "track.donate", + "columnName": "donate", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id", + "repoUrl" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "version", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `repoUrl` TEXT NOT NULL, `timestamp` REAL NOT NULL, `version` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `zipUrl` TEXT NOT NULL, `changelog` TEXT NOT NULL, PRIMARY KEY(`id`, `repoUrl`, `versionCode`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoUrl", + "columnName": "repoUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "zipUrl", + "columnName": "zipUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "changelog", + "columnName": "changelog", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id", + "repoUrl", + "versionCode" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "local", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `version` TEXT NOT NULL, `versionCode` INTEGER NOT NULL, `author` TEXT NOT NULL, `description` TEXT NOT NULL, `state` TEXT NOT NULL, `updateJson` TEXT NOT NULL, `lastUpdated` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "versionCode", + "columnName": "versionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "updateJson", + "columnName": "updateJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastUpdated", + "columnName": "lastUpdated", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "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, 'b1bfea045a8aae2b31e57dcfb1f9a45c')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/AppDatabase.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/AppDatabase.kt index 1d4f38b2..6d38b611 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/AppDatabase.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/AppDatabase.kt @@ -4,22 +4,20 @@ import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -import androidx.room.migration.Migration import dev.sanmer.mrepo.database.dao.JoinDao import dev.sanmer.mrepo.database.dao.LocalDao import dev.sanmer.mrepo.database.dao.OnlineDao import dev.sanmer.mrepo.database.dao.RepoDao import dev.sanmer.mrepo.database.dao.VersionDao import dev.sanmer.mrepo.database.entity.LocalModuleEntity -import dev.sanmer.mrepo.database.entity.LocalModuleUpdatable import dev.sanmer.mrepo.database.entity.OnlineModuleEntity -import dev.sanmer.mrepo.database.entity.Repo +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.database.entity.VersionItemEntity @Database( entities = [ - Repo::class, - LocalModuleUpdatable::class, + RepoEntity::class, + LocalModuleEntity.Updatable::class, OnlineModuleEntity::class, VersionItemEntity::class, LocalModuleEntity::class @@ -34,167 +32,9 @@ abstract class AppDatabase : RoomDatabase() { abstract fun joinDao(): JoinDao companion object { - /** - * Only migrate data for [Repo] and [LocalModuleUpdatable] - */ fun build(context: Context) = Room.databaseBuilder(context, AppDatabase::class.java, "mrepo") - .addMigrations( - MIGRATION_3_4, - MIGRATION_4_5, - MIGRATION_5_6, - MIGRATION_6_7, - MIGRATION_7_8, - MIGRATION_8_9 - ) .build() - - private val MIGRATION_3_4 = Migration(3, 4) { - it.execSQL("CREATE TABLE IF NOT EXISTS localModules (" + - "id TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "author TEXT NOT NULL, " + - "description TEXT NOT NULL, " + - "state TEXT NOT NULL, " + - "PRIMARY KEY(id))") - - it.execSQL("CREATE TABLE IF NOT EXISTS onlineModules (" + - "id TEXT NOT NULL, " + - "repoUrl TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "author TEXT NOT NULL, " + - "description TEXT NOT NULL, " + - "license TEXT NOT NULL, " + - "PRIMARY KEY(id, repoUrl))") - - it.execSQL("DROP TABLE online_module") - it.execSQL("ALTER TABLE repo RENAME TO repos") - } - - private val MIGRATION_4_5 = Migration(4, 5) { - it.execSQL("CREATE TABLE IF NOT EXISTS versions (" + - "id TEXT NOT NULL, " + - "repoUrl TEXT NOT NULL, " + - "timestamp REAL NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "zipUrl TEXT NOT NULL, " + - "changelog TEXT NOT NULL, " + - "PRIMARY KEY(id, repoUrl, versionCode))") - - it.execSQL("CREATE TABLE IF NOT EXISTS repos_new (" + - "url TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "enable INTEGER NOT NULL, " + - "version INTEGER NOT NULL, " + - "timestamp REAL NOT NULL, " + - "size INTEGER NOT NULL, " + - "PRIMARY KEY(url))") - - it.execSQL("INSERT INTO repos_new (" + - "url, name, enable, version, timestamp, size) " + - "SELECT " + - "url, name, enable, 0, timestamp, size " + - "FROM repos") - - it.execSQL("DROP TABLE repos") - it.execSQL("ALTER TABLE repos_new RENAME TO repos") - - it.execSQL("CREATE TABLE IF NOT EXISTS onlineModules_new (" + - "id TEXT NOT NULL, " + - "repoUrl TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "author TEXT NOT NULL, " + - "description TEXT NOT NULL, " + - "type TEXT NOT NULL, " + - "added REAL NOT NULL, " + - "license TEXT NOT NULL, " + - "homepage TEXT NOT NULL, " + - "source TEXT NOT NULL, " + - "support TEXT NOT NULL, " + - "donate TEXT NOT NULL, " + - "PRIMARY KEY(id, repoUrl))") - - it.execSQL("DROP TABLE onlineModules") - it.execSQL("ALTER TABLE onlineModules_new RENAME TO onlineModules") - } - - private val MIGRATION_5_6 = Migration(5, 6) { - it.execSQL("CREATE TABLE IF NOT EXISTS localModules_new (" + - "id TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "author TEXT NOT NULL, " + - "description TEXT NOT NULL, " + - "state TEXT NOT NULL, " + - "updateJson TEXT NOT NULL, " + - "PRIMARY KEY(id))") - - it.execSQL("DROP TABLE localModules") - it.execSQL("ALTER TABLE localModules_new RENAME TO localModules") - } - - private val MIGRATION_6_7 = Migration(6, 7) { - it.execSQL("CREATE TABLE IF NOT EXISTS localModules_new (" + - "id TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "author TEXT NOT NULL, " + - "description TEXT NOT NULL, " + - "state TEXT NOT NULL, " + - "updateJson TEXT NOT NULL, " + - "ignoreUpdates INTEGER NOT NULL, " + - "PRIMARY KEY(id))") - - it.execSQL("DROP TABLE localModules") - it.execSQL("ALTER TABLE localModules_new RENAME TO localModules") - } - - private val MIGRATION_7_8 = Migration(7, 8) { - it.execSQL("CREATE TABLE IF NOT EXISTS localModules_new (" + - "id TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "author TEXT NOT NULL, " + - "description TEXT NOT NULL, " + - "state TEXT NOT NULL, " + - "updateJson TEXT NOT NULL, " + - "PRIMARY KEY(id))") - - it.execSQL("CREATE TABLE IF NOT EXISTS localModules_updatable (" + - "id TEXT NOT NULL, " + - "updatable INTEGER NOT NULL, " + - "PRIMARY KEY(id))") - - it.execSQL("DROP TABLE localModules") - it.execSQL("ALTER TABLE localModules_new RENAME TO localModules") - } - - private val MIGRATION_8_9 = Migration(8, 9) { - it.execSQL("CREATE TABLE IF NOT EXISTS localModules_new (" + - "id TEXT NOT NULL, " + - "name TEXT NOT NULL, " + - "version TEXT NOT NULL, " + - "versionCode INTEGER NOT NULL, " + - "author TEXT NOT NULL, " + - "description TEXT NOT NULL, " + - "state TEXT NOT NULL, " + - "updateJson TEXT NOT NULL, " + - "lastUpdated INTEGER NOT NULL, " + - "PRIMARY KEY(id))") - - it.execSQL("DROP TABLE localModules") - it.execSQL("ALTER TABLE localModules_new RENAME TO localModules") - } } } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/JoinDao.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/JoinDao.kt index 04043975..28fd999c 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/JoinDao.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/JoinDao.kt @@ -4,32 +4,31 @@ import androidx.room.Dao import androidx.room.Query import dev.sanmer.mrepo.database.entity.OnlineModuleEntity import dev.sanmer.mrepo.database.entity.VersionItemEntity -import dev.sanmer.mrepo.model.online.ModulesJson import kotlinx.coroutines.flow.Flow @Dao interface JoinDao { @Query( - "SELECT m.* " + - "FROM onlineModules m " + - "JOIN repos r ON m.repoUrl = r.url " + - "WHERE r.enable = 1 AND r.version = :version" + "SELECT * " + + "FROM online JOIN repo " + + "ON online.repoUrl = repo.url " + + "WHERE repo.enable = 1" ) - fun getOnlineAllAsFlow(version: Int = ModulesJson.CURRENT_VERSION): Flow> + fun getOnlineAllAsFlow(): Flow> @Query( - "SELECT m.* " + - "FROM onlineModules m " + - "JOIN repos r ON m.repoUrl = r.url " + - "WHERE m.id = :id AND m.repoUrl = :repoUrl AND r.enable = 1 AND r.version = :version LIMIT 1" + "SELECT online.* " + + "FROM online JOIN repo " + + "ON online.repoUrl = repo.url " + + "WHERE online.id = :id AND online.repoUrl = :repoUrl AND repo.enable = 1 LIMIT 1" ) - suspend fun getOnlineByIdAndUrl(id: String, repoUrl: String, version: Int = ModulesJson.CURRENT_VERSION): OnlineModuleEntity + suspend fun getOnlineByIdAndUrl(id: String, repoUrl: String): OnlineModuleEntity @Query( - "SELECT v.* " + - "FROM versions v " + - "JOIN repos r ON v.repoUrl = r.url " + - "WHERE v.id = :id AND r.enable = 1 AND r.version = :version ORDER BY v.versionCode DESC" + "SELECT version.* " + + "FROM version JOIN repo " + + "ON version.repoUrl = repo.url " + + "WHERE version.id = :id AND repo.enable = 1 ORDER BY version.versionCode DESC" ) - suspend fun getVersionById(id: String, version: Int = ModulesJson.CURRENT_VERSION): List + suspend fun getVersionById(id: String): List } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/LocalDao.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/LocalDao.kt index 90a8f3e9..0889417f 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/LocalDao.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/LocalDao.kt @@ -6,15 +6,14 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import dev.sanmer.mrepo.database.entity.LocalModuleEntity -import dev.sanmer.mrepo.database.entity.LocalModuleUpdatable import kotlinx.coroutines.flow.Flow @Dao interface LocalDao { - @Query("SELECT * FROM localModules") + @Query("SELECT * FROM local") fun getAllAsFlow(): Flow> - @Query("SELECT * FROM localModules WHERE id = :id LIMIT 1") + @Query("SELECT * FROM local WHERE id = :id LIMIT 1") suspend fun getByIdOrNull(id: String): LocalModuleEntity? @Insert(onConflict = OnConflictStrategy.REPLACE) @@ -23,18 +22,18 @@ interface LocalDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(list: List) - @Query("DELETE FROM localModules") + @Query("DELETE FROM local") suspend fun deleteAll() - @Query("SELECT * FROM localModules_updatable") - suspend fun getUpdatableTagAll(): List + @Query("SELECT * FROM local_updatable") + suspend fun getUpdatableTagAll(): List @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insertUpdatableTag(value: LocalModuleUpdatable) + suspend fun insertUpdatableTag(value: LocalModuleEntity.Updatable) - @Query("SELECT * FROM localModules_updatable WHERE id = :id LIMIT 1") - suspend fun hasUpdatableTagOrNull(id: String): LocalModuleUpdatable? + @Query("SELECT * FROM local_updatable WHERE id = :id LIMIT 1") + suspend fun hasUpdatableTagOrNull(id: String): LocalModuleEntity.Updatable? @Delete - suspend fun deleteUpdatableTag(values: List) + suspend fun deleteUpdatableTag(values: List) } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/OnlineDao.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/OnlineDao.kt index d37a770d..89c408a4 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/OnlineDao.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/OnlineDao.kt @@ -8,12 +8,12 @@ import dev.sanmer.mrepo.database.entity.OnlineModuleEntity @Dao interface OnlineDao { - @Query("SELECT * FROM onlineModules WHERE id = :id") + @Query("SELECT * FROM online WHERE id = :id") suspend fun getAllById(id: String): List @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(list: List) - @Query("DELETE from onlineModules WHERE repoUrl = :repoUrl") + @Query("DELETE FROM online WHERE repoUrl = :repoUrl") suspend fun deleteByUrl(repoUrl: String) } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/RepoDao.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/RepoDao.kt index 1c8f77dc..4e813e71 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/RepoDao.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/RepoDao.kt @@ -5,23 +5,23 @@ import androidx.room.Delete import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import dev.sanmer.mrepo.database.entity.Repo +import dev.sanmer.mrepo.database.entity.RepoEntity import kotlinx.coroutines.flow.Flow @Dao interface RepoDao { - @Query("SELECT * FROM repos") - fun getAllAsFlow(): Flow> + @Query("SELECT * FROM repo") + fun getAllAsFlow(): Flow> - @Query("SELECT * FROM repos") - suspend fun getAll(): List + @Query("SELECT * FROM repo") + suspend fun getAll(): List - @Query("SELECT * FROM repos WHERE url = :url LIMIT 1") - suspend fun getByUrl(url: String): Repo + @Query("SELECT * FROM repo WHERE url = :url LIMIT 1") + suspend fun getByUrl(url: String): RepoEntity @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(value: Repo) + suspend fun insert(value: RepoEntity) @Delete - suspend fun delete(value: Repo) + suspend fun delete(value: RepoEntity) } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/VersionDao.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/VersionDao.kt index 82c19a8f..c010b1ec 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/VersionDao.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/VersionDao.kt @@ -11,6 +11,6 @@ interface VersionDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(list: List) - @Query("DELETE from versions WHERE repoUrl = :repoUrl") + @Query("DELETE FROM version WHERE repoUrl = :repoUrl") suspend fun deleteByUrl(repoUrl: String) } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Local.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Local.kt index 1d2a2b31..c9f0e960 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Local.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Local.kt @@ -5,7 +5,7 @@ import androidx.room.PrimaryKey import dev.sanmer.mrepo.model.local.LocalModule import dev.sanmer.mrepo.model.local.State -@Entity(tableName = "localModules") +@Entity(tableName = "local") data class LocalModuleEntity( @PrimaryKey val id: String, val name: String, @@ -40,10 +40,10 @@ data class LocalModuleEntity( state = State.valueOf(state), lastUpdated = lastUpdated ) -} -@Entity(tableName = "localModules_updatable") -data class LocalModuleUpdatable( - @PrimaryKey val id: String, - val updatable: Boolean -) \ No newline at end of file + @Entity(tableName = "local_updatable") + data class Updatable( + @PrimaryKey val id: String, + val updatable: Boolean + ) +} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Online.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Online.kt index 32b9bb46..b6b0cb72 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Online.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Online.kt @@ -5,7 +5,10 @@ import androidx.room.Entity import dev.sanmer.mrepo.model.online.OnlineModule import dev.sanmer.mrepo.model.online.TrackJson -@Entity(tableName = "onlineModules", primaryKeys = ["id", "repoUrl"]) +@Entity( + tableName = "online", + primaryKeys = ["id", "repoUrl"] +) data class OnlineModuleEntity( val id: String, val repoUrl: String, @@ -14,7 +17,7 @@ data class OnlineModuleEntity( val versionCode: Int, val author: String, val description: String, - @Embedded val track: TrackJsonEntity + @Embedded val track: Track ) { constructor( original: OnlineModule, @@ -27,7 +30,7 @@ data class OnlineModuleEntity( versionCode = original.versionCode, author = original.author, description = original.description, - track = TrackJsonEntity(original.track) + track = Track(original.track) ) fun toModule() = OnlineModule( @@ -40,35 +43,34 @@ data class OnlineModuleEntity( track = track.toTrack(), versions = listOf() ) -} -@Entity(tableName = "track") -data class TrackJsonEntity( - val type: String, - val added: Float, - val license: String, - val homepage: String, - val source: String, - val support: String, - val donate: String -) { - constructor(original: TrackJson) : this( - type = original.type.name, - added = original.added, - license = original.license, - homepage = original.homepage, - source = original.source, - support = original.support, - donate = original.donate - ) + data class Track( + val type: String, + val added: Float, + val license: String, + val homepage: String, + val source: String, + val support: String, + val donate: String + ) { + constructor(original: TrackJson) : this( + type = original.type.name, + added = original.added, + license = original.license, + homepage = original.homepage, + source = original.source, + support = original.support, + donate = original.donate + ) - fun toTrack() = TrackJson( - typeName = type, - added = added, - license = license, - homepage = homepage, - source = source, - support = support, - donate = donate - ) + fun toTrack() = TrackJson( + typeName = type, + added = added, + license = license, + homepage = homepage, + source = source, + support = support, + donate = donate + ) + } } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Repo.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Repo.kt index 391f8581..64c9f7f3 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Repo.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Repo.kt @@ -5,18 +5,16 @@ import androidx.room.Entity import androidx.room.PrimaryKey import dev.sanmer.mrepo.model.online.ModulesJson -@Entity(tableName = "repos") -data class Repo( +@Entity(tableName = "repo") +data class RepoEntity( @PrimaryKey val url: String, val name: String = url, val enable: Boolean = true, - @Embedded val metadata: RepoMetadata = RepoMetadata.default() + @Embedded val metadata: Metadata = Metadata.default() ) { - val isCompatible get() = metadata.version == ModulesJson.CURRENT_VERSION - override fun equals(other: Any?): Boolean { return when (other) { - is Repo -> url == other.url + is RepoEntity -> url == other.url else -> false } } @@ -27,29 +25,25 @@ data class Repo( fun copy(modulesJson: ModulesJson) = copy( name = modulesJson.name, - metadata = RepoMetadata( - version = modulesJson.metadata.version, + metadata = Metadata( timestamp = modulesJson.metadata.timestamp, size = modulesJson.modules.size ) ) - companion object { - fun String.toRepo() = Repo(url = this) + data class Metadata( + val timestamp: Float, + val size: Int + ) { + companion object { + fun default() = Metadata( + timestamp = 0f, + size = 0 + ) + } } -} -@Entity(tableName = "metadata") -data class RepoMetadata( - val version: Int, - val timestamp: Float, - val size: Int -) { companion object { - fun default() = RepoMetadata( - version = ModulesJson.CURRENT_VERSION, - timestamp = 0f, - size = 0 - ) + fun String.toRepo() = RepoEntity(url = this) } } diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Version.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Version.kt index e4a87537..36f82910 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Version.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Version.kt @@ -3,7 +3,10 @@ package dev.sanmer.mrepo.database.entity import androidx.room.Entity import dev.sanmer.mrepo.model.online.VersionItem -@Entity(tableName = "versions", primaryKeys = ["id", "repoUrl", "versionCode"]) +@Entity( + tableName = "version", + primaryKeys = ["id", "repoUrl", "versionCode"] +) data class VersionItemEntity( val id: String, val repoUrl: String, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/ModulesJson.kt b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/ModulesJson.kt index c886c167..54864116 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/ModulesJson.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/ModulesJson.kt @@ -5,23 +5,17 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class ModulesJson( val name: String, - val metadata: ModulesJsonMetadata = ModulesJsonMetadata.default(), + val metadata: Metadata = Metadata.default(), val modules: List ) { - companion object { - const val CURRENT_VERSION = 1 - } -} - -@JsonClass(generateAdapter = true) -data class ModulesJsonMetadata( - val version: Int, - val timestamp: Float -) { - companion object { - fun default() = ModulesJsonMetadata( - version = 0, - timestamp = 0f - ) + @JsonClass(generateAdapter = true) + data class Metadata( + val timestamp: Float + ) { + companion object { + fun default() = Metadata( + timestamp = 0f + ) + } } } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/OnlineModule.kt b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/OnlineModule.kt index b77fca39..241facc6 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/OnlineModule.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/OnlineModule.kt @@ -14,7 +14,9 @@ data class OnlineModule( val track: TrackJson, val versions: List, ) { - val versionDisplay get() = Utils.getVersionDisplay(version, versionCode) + val versionDisplay by lazy { + Utils.getVersionDisplay(version, versionCode) + } override fun equals(other: Any?): Boolean { return when (other) { diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/TrackJson.kt b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/TrackJson.kt index dfbb3790..6a31cc2d 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/TrackJson.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/TrackJson.kt @@ -5,7 +5,8 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class TrackJson( - @Json(name = "type") val typeName: String, + @Json(name = "type") + val typeName: String, val added: Float, val license: String = "", val homepage: String = "", @@ -13,16 +14,18 @@ data class TrackJson( val support: String = "", val donate: String = "" ) { - val type = TrackType.valueOf(typeName) - val hasLicense get() = license.isNotBlank() - && license.uppercase() != "UNKNOWN" -} + val type = Type.valueOf(typeName) -enum class TrackType { - UNKNOWN, - ONLINE_JSON, - ONLINE_ZIP, - GIT, - LOCAL_JSON, - LOCAL_ZIP, + val hasLicense by lazy { + license.isNotBlank() && license.uppercase() != "UNKNOWN" + } + + enum class Type { + UNKNOWN, + ONLINE_JSON, + ONLINE_ZIP, + GIT, + LOCAL_JSON, + LOCAL_ZIP, + } } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/VersionItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/VersionItem.kt index f121975e..ae412544 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/VersionItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/model/online/VersionItem.kt @@ -13,5 +13,7 @@ data class VersionItem( val zipUrl: String, val changelog: String ) { - val versionDisplay get() = Utils.getVersionDisplay(version, versionCode) + val versionDisplay by lazy { + Utils.getVersionDisplay(version, versionCode) + } } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/model/state/OnlineState.kt b/app/src/main/kotlin/dev/sanmer/mrepo/model/state/OnlineState.kt deleted file mode 100644 index 059258d5..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/state/OnlineState.kt +++ /dev/null @@ -1,42 +0,0 @@ -package dev.sanmer.mrepo.model.state - -import dev.sanmer.mrepo.model.local.LocalModule -import dev.sanmer.mrepo.model.online.OnlineModule - -data class OnlineState( - val installed: Boolean, - val updatable: Boolean, - val hasLicense: Boolean, - val lastUpdated: Float -) { - @Suppress("FloatingPointLiteralPrecision") - companion object { - fun OnlineModule.createState( - local: LocalModule?, - hasUpdatableTag: Boolean, - ): OnlineState { - val installed = local != null && local.id == id - && local.author == author - - val updatable = if (installed && hasUpdatableTag) { - local!!.versionCode < versionCode - } else { - false - } - - return OnlineState( - installed = installed, - updatable = updatable, - hasLicense = track.license.isNotBlank(), - lastUpdated = versions.firstOrNull()?.timestamp ?: 1473339588.0f - ) - } - - fun example() = OnlineState( - installed = true, - updatable = false, - hasLicense = true, - lastUpdated = 1660640580.0f - ) - } -} diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/model/state/RepoState.kt b/app/src/main/kotlin/dev/sanmer/mrepo/model/state/RepoState.kt deleted file mode 100644 index 70d5dd9a..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/state/RepoState.kt +++ /dev/null @@ -1,37 +0,0 @@ -package dev.sanmer.mrepo.model.state - -import androidx.compose.runtime.Immutable -import dev.sanmer.mrepo.database.entity.Repo -import dev.sanmer.mrepo.database.entity.RepoMetadata - -@Immutable -data class RepoState( - val url: String, - val name: String, - val enable: Boolean, - val compatible: Boolean, - val version: Int, - val timestamp: Float, - val size: Int -) { - constructor(repo: Repo) : this( - url = repo.url, - name = repo.name, - enable = repo.enable, - compatible = repo.isCompatible, - version = repo.metadata.version, - timestamp = repo.metadata.timestamp, - size = repo.metadata.size - ) - - fun toRepo() = Repo( - url = url, - name = name, - enable = enable, - metadata = RepoMetadata( - version = version, - timestamp = timestamp, - size = size - ) - ) -} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt b/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt index 9fef9479..6685b18a 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt @@ -6,9 +6,8 @@ import dev.sanmer.mrepo.database.dao.OnlineDao import dev.sanmer.mrepo.database.dao.RepoDao import dev.sanmer.mrepo.database.dao.VersionDao import dev.sanmer.mrepo.database.entity.LocalModuleEntity -import dev.sanmer.mrepo.database.entity.LocalModuleUpdatable import dev.sanmer.mrepo.database.entity.OnlineModuleEntity -import dev.sanmer.mrepo.database.entity.Repo +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.database.entity.VersionItemEntity import dev.sanmer.mrepo.model.local.LocalModule import dev.sanmer.mrepo.model.online.OnlineModule @@ -49,7 +48,7 @@ class LocalRepository @Inject constructor( suspend fun insertUpdatableTag(id: String, updatable: Boolean) = withContext(Dispatchers.IO) { localDao.insertUpdatableTag( - LocalModuleUpdatable( + LocalModuleEntity.Updatable( id = id, updatable = updatable ) @@ -75,11 +74,11 @@ class LocalRepository @Inject constructor( repoDao.getByUrl(url) } - suspend fun insertRepo(value: Repo) = withContext(Dispatchers.IO) { + suspend fun insertRepo(value: RepoEntity) = withContext(Dispatchers.IO) { repoDao.insert(value) } - suspend fun deleteRepo(value: Repo) = withContext(Dispatchers.IO) { + suspend fun deleteRepo(value: RepoEntity) = withContext(Dispatchers.IO) { repoDao.delete(value) } @@ -87,17 +86,15 @@ class LocalRepository @Inject constructor( val values = mutableListOf() list.forEach { entity -> val new = entity.toModule() - - if (new in values) { + if (values.contains(new)) { val old = values.first { it.id == new.id } if (new.versionCode > old.versionCode) { values.remove(old) values.add(new.copy(versions = old.versions)) } } else { - values.add( - new.copy(versions = getVersionById(new.id)) - ) + val versions = getVersionById(new.id) + values.add(new.copy(versions = versions)) } } @@ -113,6 +110,13 @@ class LocalRepository @Inject constructor( } suspend fun insertOnline(list: List, repoUrl: String) = withContext(Dispatchers.IO) { + val modules = list.map { + OnlineModuleEntity( + original = it, + repoUrl = repoUrl + ) + } + val versions = list.map { module -> module.versions.map { VersionItemEntity( @@ -124,14 +128,7 @@ class LocalRepository @Inject constructor( }.merge() versionDao.insert(versions) - onlineDao.insert( - list.map { - OnlineModuleEntity( - original = it, - repoUrl = repoUrl - ) - } - ) + onlineDao.insert(modules) } suspend fun deleteOnlineByUrl(repoUrl: String) = withContext(Dispatchers.IO) { diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt b/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt index e4986007..153beb92 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt @@ -1,7 +1,7 @@ package dev.sanmer.mrepo.repository import dev.sanmer.mrepo.Compat -import dev.sanmer.mrepo.database.entity.Repo +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.network.runRequest import dev.sanmer.mrepo.stub.IRepoManager import kotlinx.coroutines.Dispatchers @@ -36,7 +36,7 @@ class ModulesRepository @Inject constructor( getRepo(it) } - suspend fun getRepo(repo: Repo) = withContext(Dispatchers.IO) { + suspend fun getRepo(repo: RepoEntity) = withContext(Dispatchers.IO) { runRequest { val api = IRepoManager.build(repo.url) return@runRequest api.modules.execute() diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/activity/MainActivity.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/activity/MainActivity.kt index 6d24c8ea..0dd25125 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/activity/MainActivity.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/activity/MainActivity.kt @@ -18,7 +18,7 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import dev.sanmer.mrepo.Compat import dev.sanmer.mrepo.app.Const -import dev.sanmer.mrepo.database.entity.Repo.Companion.toRepo +import dev.sanmer.mrepo.database.entity.RepoEntity.Companion.toRepo import dev.sanmer.mrepo.datastore.UserPreferencesCompat.Companion.isRoot import dev.sanmer.mrepo.datastore.UserPreferencesCompat.Companion.isSetup import dev.sanmer.mrepo.datastore.WorkingMode diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModuleItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModuleItem.kt index 095c232e..9f79afa5 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModuleItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModuleItem.kt @@ -20,6 +20,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -56,6 +59,10 @@ fun ModuleItem( val userPreferences = LocalUserPreferences.current val menu = userPreferences.modulesMenu + val versionDisplay by remember { + derivedStateOf { module.versionDisplay } + } + Box( modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center @@ -83,8 +90,7 @@ fun ModuleItem( ) Text( - text = stringResource(id = R.string.module_version_author, - module.versionDisplay, module.author), + text = stringResource(id = R.string.module_version_author, versionDisplay, module.author), style = MaterialTheme.typography.bodySmall, textDecoration = decoration, color = MaterialTheme.colorScheme.onSurfaceVariant @@ -92,8 +98,7 @@ fun ModuleItem( if (module.lastUpdated != 0L && menu.showUpdatedTime) { Text( - text = stringResource(id = R.string.module_update_at, - module.lastUpdated.toDate()), + text = stringResource(id = R.string.module_update_at, module.lastUpdated.toDate()), style = MaterialTheme.typography.bodySmall, textDecoration = decoration, color = MaterialTheme.colorScheme.outline diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModuleItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModuleItem.kt index f4061465..375b1df1 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModuleItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModuleItem.kt @@ -22,11 +22,11 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R import dev.sanmer.mrepo.model.online.OnlineModule -import dev.sanmer.mrepo.model.state.OnlineState import dev.sanmer.mrepo.ui.component.LabelItem import dev.sanmer.mrepo.ui.component.Logo import dev.sanmer.mrepo.ui.providable.LocalUserPreferences import dev.sanmer.mrepo.utils.extensions.toDate +import dev.sanmer.mrepo.viewmodel.RepositoryViewModel.OnlineState @Composable fun ModuleItem( diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModulesList.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModulesList.kt index 594da6d2..6250f196 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModulesList.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/ModulesList.kt @@ -12,10 +12,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.navigation.NavController import dev.sanmer.mrepo.model.online.OnlineModule -import dev.sanmer.mrepo.model.state.OnlineState import dev.sanmer.mrepo.ui.component.scrollbar.VerticalFastScrollbar import dev.sanmer.mrepo.ui.utils.navigateSingleTopTo import dev.sanmer.mrepo.viewmodel.ModuleViewModel +import dev.sanmer.mrepo.viewmodel.RepositoryViewModel.OnlineState @Composable fun ModulesList( diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/RepositoryMenu.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/RepositoryMenu.kt index e9a30867..a7213b1b 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/RepositoryMenu.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/RepositoryMenu.kt @@ -31,7 +31,6 @@ import dev.sanmer.mrepo.R import dev.sanmer.mrepo.datastore.Option import dev.sanmer.mrepo.datastore.RepositoryMenuCompat import dev.sanmer.mrepo.model.online.OnlineModule -import dev.sanmer.mrepo.model.state.OnlineState import dev.sanmer.mrepo.ui.component.MenuChip import dev.sanmer.mrepo.ui.component.NavigationBarsSpacer import dev.sanmer.mrepo.ui.component.Segment @@ -39,6 +38,7 @@ import dev.sanmer.mrepo.ui.component.SegmentedButtons import dev.sanmer.mrepo.ui.component.SegmentedButtonsDefaults import dev.sanmer.mrepo.ui.providable.LocalUserPreferences import dev.sanmer.mrepo.ui.utils.expandedShape +import dev.sanmer.mrepo.viewmodel.RepositoryViewModel.OnlineState val options = listOf( Option.Name to R.string.menu_sort_option_name, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTopBar.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTopBar.kt index 40b7ad15..ba10d41b 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTopBar.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTopBar.kt @@ -24,7 +24,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.navigation.NavController import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.database.entity.Repo +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.model.online.OnlineModule import dev.sanmer.mrepo.model.online.TrackJson import dev.sanmer.mrepo.ui.component.CollapsingTopAppBar @@ -39,7 +39,7 @@ import dev.sanmer.mrepo.utils.extensions.openUrl @Composable fun ViewTopBar( online: OnlineModule, - tracks: List>, + tracks: List>, scrollBehavior: TopAppBarScrollBehavior, navController: NavController ) = CollapsingTopAppBar( @@ -74,7 +74,7 @@ fun ViewTopBar( @Composable private fun topBarContent( module: OnlineModule, - tracks: List> + tracks: List> ) : @Composable ColumnScope.() -> Unit = { val userPreferences = LocalUserPreferences.current val repositoryMenu = userPreferences.repositoryMenu diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TrackItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TrackItem.kt index e0413439..8c3b6ed1 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TrackItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TrackItem.kt @@ -31,7 +31,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.database.entity.Repo +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.model.online.TrackJson import dev.sanmer.mrepo.ui.component.NavigationBarsSpacer import dev.sanmer.mrepo.ui.utils.expandedShape @@ -39,7 +39,7 @@ import dev.sanmer.mrepo.utils.extensions.toDateTime @Composable fun TrackItem( - tracks: List> + tracks: List> ) = Box { var open by rememberSaveable { mutableStateOf(false) } @@ -86,7 +86,7 @@ fun TrackItem( @Composable private fun ValueItem( - repo: Repo, + repo: RepoEntity, track: TrackJson ) = Surface( modifier = Modifier.fillMaxWidth(), diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/OverviewPage.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/OverviewPage.kt index a2fe6f67..47db0b4a 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/OverviewPage.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/OverviewPage.kt @@ -20,6 +20,9 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -158,9 +161,13 @@ private fun LocalItem( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(16.dp) ) { + val versionDisplay by remember { + derivedStateOf { local.versionDisplay } + } + ValueItem( key = stringResource(id = R.string.view_module_version), - value = local.versionDisplay, + value = versionDisplay, modifier = Modifier.weight(1f) ) diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/VersionsPage.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/VersionsPage.kt index 2409e137..9d94bb74 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/VersionsPage.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/VersionsPage.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.database.entity.Repo +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.model.online.VersionItem import dev.sanmer.mrepo.ui.component.LabelItem import dev.sanmer.mrepo.ui.component.VersionItemBottomSheet @@ -33,7 +33,7 @@ import dev.sanmer.mrepo.utils.extensions.toDate @Composable fun VersionsPage( - versions: List>, + versions: List>, localVersionCode: Int, isProviderAlive: Boolean, getProgress: @Composable (VersionItem) -> Float, @@ -71,7 +71,7 @@ fun VersionsPage( @Composable private fun VersionItem( item: VersionItem, - repo: Repo, + repo: RepoEntity, localVersionCode: Int, isProviderAlive: Boolean, onDownload: (Boolean) -> Unit diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesList.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesList.kt index 1dba5040..b651cee5 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesList.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesList.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.model.state.RepoState +import dev.sanmer.mrepo.viewmodel.RepositoriesViewModel.RepoState @Composable fun RepositoriesList( diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoryItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoryItem.kt index 626cd0db..650a0ef5 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoryItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoryItem.kt @@ -40,12 +40,12 @@ import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.model.state.RepoState import dev.sanmer.mrepo.ui.component.LabelItem import dev.sanmer.mrepo.ui.component.NavigationBarsSpacer import dev.sanmer.mrepo.ui.utils.expandedShape import dev.sanmer.mrepo.utils.extensions.shareText import dev.sanmer.mrepo.utils.extensions.toDateTime +import dev.sanmer.mrepo.viewmodel.RepositoriesViewModel.RepoState @Composable fun RepositoryItem( @@ -60,7 +60,6 @@ fun RepositoryItem( onClick = { toggle(!repo.enable) }, ) { val (alpha, textDecoration) = when { - !repo.compatible -> 0.5f to TextDecoration.LineThrough !repo.enable -> 0.5f to TextDecoration.None else -> 1f to TextDecoration.None } @@ -119,18 +118,10 @@ fun RepositoryItem( ) } - if (repo.compatible) { - LabelItem( - text = stringResource(id = R.string.repo_modules, repo.size), - upperCase = false - ) - } else { - LabelItem( - text = stringResource(id = R.string.repo_incompatible), - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError - ) - } + LabelItem( + text = stringResource(id = R.string.repo_modules, repo.size), + upperCase = false + ) } Row( diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt index 0cef6834..efafc659 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt @@ -12,8 +12,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewModelScope import dev.sanmer.mrepo.Compat -import dev.sanmer.mrepo.database.entity.Repo -import dev.sanmer.mrepo.database.entity.Repo.Companion.toRepo +import dev.sanmer.mrepo.database.entity.RepoEntity +import dev.sanmer.mrepo.database.entity.RepoEntity.Companion.toRepo import dev.sanmer.mrepo.model.json.UpdateJson import dev.sanmer.mrepo.model.local.LocalModule import dev.sanmer.mrepo.model.online.OnlineModule @@ -63,8 +63,8 @@ class ModuleViewModel @Inject constructor( versions.count { it.second.versionCode > localVersionCode } } - val versions = mutableStateListOf>() - val tracks = mutableStateListOf>() + val versions = mutableStateListOf>() + val tracks = mutableStateListOf>() init { Timber.d("ModuleViewModel init: $moduleId") diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt index 01ab2665..9f67d568 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt @@ -1,15 +1,16 @@ package dev.sanmer.mrepo.viewmodel +import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import dev.sanmer.mrepo.database.entity.Repo.Companion.toRepo -import dev.sanmer.mrepo.model.state.RepoState +import dev.sanmer.mrepo.database.entity.RepoEntity.Companion.toRepo import dev.sanmer.mrepo.repository.LocalRepository import dev.sanmer.mrepo.repository.ModulesRepository import dagger.hilt.android.lifecycle.HiltViewModel +import dev.sanmer.mrepo.database.entity.RepoEntity import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn @@ -86,4 +87,31 @@ class RepositoriesViewModel @Inject constructor( modulesRepository.getRepoAll(onlyEnable = false) } } + + @Immutable + data class RepoState( + val url: String, + val name: String, + val enable: Boolean, + val timestamp: Float, + val size: Int + ) { + constructor(repo: RepoEntity) : this( + url = repo.url, + name = repo.name, + enable = repo.enable, + timestamp = repo.metadata.timestamp, + size = repo.metadata.size + ) + + fun toRepo() = RepoEntity( + url = url, + name = name, + enable = enable, + metadata = RepoEntity.Metadata( + timestamp = timestamp, + size = size + ) + ) + } } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt index 3b142660..3c79530e 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt @@ -1,5 +1,6 @@ package dev.sanmer.mrepo.viewmodel +import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue @@ -8,11 +9,9 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import dev.sanmer.mrepo.datastore.Option import dev.sanmer.mrepo.datastore.RepositoryMenuCompat +import dev.sanmer.mrepo.model.local.LocalModule import dev.sanmer.mrepo.model.online.OnlineModule -import dev.sanmer.mrepo.model.state.OnlineState -import dev.sanmer.mrepo.model.state.OnlineState.Companion.createState import dev.sanmer.mrepo.repository.LocalRepository -import dev.sanmer.mrepo.repository.ModulesRepository import dev.sanmer.mrepo.repository.UserPreferencesRepository import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -26,7 +25,6 @@ import javax.inject.Inject @HiltViewModel class RepositoryViewModel @Inject constructor( private val localRepository: LocalRepository, - private val modulesRepository: ModulesRepository, private val userPreferencesRepository: UserPreferencesRepository ) : ViewModel() { private val repositoryMenu get() = userPreferencesRepository.data @@ -135,4 +133,42 @@ class RepositoryViewModel @Inject constructor( userPreferencesRepository.setRepositoryMenu(value) } } + + private fun OnlineModule.createState( + local: LocalModule?, + hasUpdatableTag: Boolean, + ): OnlineState { + val installed = local != null && local.id == id + && local.author == author + + val updatable = if (installed && hasUpdatableTag) { + local!!.versionCode < versionCode + } else { + false + } + + return OnlineState( + installed = installed, + updatable = updatable, + hasLicense = track.license.isNotBlank(), + lastUpdated = versions.firstOrNull()?.timestamp ?: 1.47333965E9f + ) + } + + @Immutable + data class OnlineState( + val installed: Boolean, + val updatable: Boolean, + val hasLicense: Boolean, + val lastUpdated: Float + ) { + companion object { + fun example() = OnlineState( + installed = true, + updatable = false, + hasLicense = true, + lastUpdated = 1.66064064E9f + ) + } + } } \ No newline at end of file