From f5eeadb0c53e49643da038aa14ae21236865986a Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 01:35:39 +0800 Subject: [PATCH 1/8] Impl new data structure - Optimize DAO for database --- .../dev/sanmer/mrepo/database/dao/JoinDao.kt | 36 +++-- .../dev/sanmer/mrepo/database/dao/LocalDao.kt | 14 +- .../sanmer/mrepo/database/dao/OnlineDao.kt | 2 +- .../dev/sanmer/mrepo/database/dao/RepoDao.kt | 3 - .../sanmer/mrepo/database/dao/VersionDao.kt | 2 +- .../dev/sanmer/mrepo/database/entity/Local.kt | 19 ++- .../sanmer/mrepo/database/entity/Online.kt | 47 +++--- .../dev/sanmer/mrepo/database/entity/Repo.kt | 52 +++---- .../sanmer/mrepo/database/entity/Version.kt | 18 ++- .../dev/sanmer/mrepo/model/json/UpdateJson.kt | 7 +- .../sanmer/mrepo/model/online/ModulesJson.kt | 15 +- .../sanmer/mrepo/model/online/OnlineModule.kt | 19 ++- .../sanmer/mrepo/model/online/TrackJson.kt | 31 ---- .../sanmer/mrepo/model/online/VersionItem.kt | 14 +- .../mrepo/repository/LocalRepository.kt | 102 ++++++------- .../mrepo/repository/ModulesRepository.kt | 49 ++++--- .../mrepo/ui/screens/repository/ModuleItem.kt | 26 ++-- .../ui/screens/repository/view/ViewScreen.kt | 1 - .../ui/screens/repository/view/ViewTopBar.kt | 24 +--- .../repository/view/items/TrackItem.kt | 135 ------------------ .../repository/view/pages/AboutPage.kt | 6 +- .../repository/view/pages/OverviewPage.kt | 6 +- .../repository/view/pages/VersionsPage.kt | 4 +- .../settings/repositories/RepositoriesList.kt | 22 +-- .../settings/repositories/RepositoryItem.kt | 19 ++- .../sanmer/mrepo/utils/extensions/ListExt.kt | 7 - .../utils/extensions/LocalDateTimeExt.kt | 19 +-- .../sanmer/mrepo/viewmodel/ModuleViewModel.kt | 39 ++--- .../mrepo/viewmodel/ModulesViewModel.kt | 10 +- .../mrepo/viewmodel/RepositoriesViewModel.kt | 45 ++---- .../mrepo/viewmodel/RepositoryViewModel.kt | 43 +++--- 31 files changed, 300 insertions(+), 536 deletions(-) delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/model/online/TrackJson.kt delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TrackItem.kt delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ListExt.kt 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 28fd999c..2a132b74 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 @@ -2,33 +2,39 @@ package dev.sanmer.mrepo.database.dao import androidx.room.Dao import androidx.room.Query +import dev.sanmer.mrepo.database.entity.LocalModuleEntity import dev.sanmer.mrepo.database.entity.OnlineModuleEntity +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.database.entity.VersionItemEntity import kotlinx.coroutines.flow.Flow @Dao interface JoinDao { @Query( - "SELECT * " + - "FROM online JOIN repo " + - "ON online.repoUrl = repo.url " + - "WHERE repo.enable = 1" + "SELECT * FROM local " + + "LEFT JOIN local_updatable ON local_updatable.id = local.id " ) - fun getOnlineAllAsFlow(): Flow> + fun getLocalWithUpdatableAll(): Flow> @Query( - "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" + "SELECT * FROM local " + + "LEFT JOIN local_updatable ON local_updatable.id = local.id " + + "WHERE local.id = :id" ) - suspend fun getOnlineByIdAndUrl(id: String, repoUrl: String): OnlineModuleEntity + suspend fun getLocalWithUpdatable(id: String): Map @Query( - "SELECT version.* " + - "FROM version JOIN repo " + - "ON version.repoUrl = repo.url " + - "WHERE version.id = :id AND repo.enable = 1 ORDER BY version.versionCode DESC" + "SELECT online.*, version.* FROM repo " + + "INNER JOIN online ON online.repo_url = repo.url " + + "INNER JOIN version ON version.id = online.id " + + "WHERE repo.disable = 0 " ) - suspend fun getVersionById(id: String): List + fun getOnlineAllAsFlow(): Flow>> + + @Query( + "SELECT * FROM repo " + + "INNER JOIN version ON version.repo_url = repo.url " + + "WHERE repo.disable = 0 AND version.id = :id " + ) + suspend fun getVersionWithRepo(id: String): Map> } \ 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 698020e7..36e1fdc0 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 @@ -16,9 +16,6 @@ interface LocalDao { @Query("SELECT * FROM local") fun getAll(): List - @Query("SELECT * FROM local WHERE id = :id LIMIT 1") - suspend fun getByIdOrNull(id: String): LocalModuleEntity? - @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(value: LocalModuleEntity) @@ -31,15 +28,12 @@ interface LocalDao { @Query("DELETE FROM local") suspend fun deleteAll() - @Query("SELECT * FROM local_updatable") - suspend fun getUpdatableTagAll(): List - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insertUpdatableTag(value: LocalModuleEntity.Updatable) + suspend fun insertUpdatable(value: LocalModuleEntity.Updatable) - @Query("SELECT * FROM local_updatable WHERE id = :id LIMIT 1") - suspend fun hasUpdatableTagOrNull(id: String): LocalModuleEntity.Updatable? + @Query("SELECT * FROM local_updatable WHERE id = :id") + suspend fun getUpdatableOrNull(id: String): LocalModuleEntity.Updatable? @Delete - suspend fun deleteUpdatableTag(values: List) + suspend fun deleteUpdatable(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 89c408a4..6a202275 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 @@ -14,6 +14,6 @@ interface OnlineDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(list: List) - @Query("DELETE FROM online WHERE repoUrl = :repoUrl") + @Query("DELETE FROM online WHERE repo_url = :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 4e813e71..779dfb76 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 @@ -16,9 +16,6 @@ interface RepoDao { @Query("SELECT * FROM repo") suspend fun getAll(): List - @Query("SELECT * FROM repo WHERE url = :url LIMIT 1") - suspend fun getByUrl(url: String): RepoEntity - @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(value: RepoEntity) 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 c010b1ec..2d559cfe 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 version WHERE repoUrl = :repoUrl") + @Query("DELETE FROM version WHERE repo_url = :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 c9f0e960..be971f66 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 @@ -1,20 +1,26 @@ package dev.sanmer.mrepo.database.entity +import androidx.room.ColumnInfo import androidx.room.Entity -import androidx.room.PrimaryKey import dev.sanmer.mrepo.model.local.LocalModule import dev.sanmer.mrepo.model.local.State -@Entity(tableName = "local") +@Entity( + tableName = "local", + primaryKeys = ["id"] +) data class LocalModuleEntity( - @PrimaryKey val id: String, + val id: String, val name: String, val version: String, + @ColumnInfo(name = "version_code") val versionCode: Int, val author: String, val description: String, val state: String, + @ColumnInfo(name = "update_json") val updateJson: String, + @ColumnInfo(name = "last_updated") val lastUpdated: Long ) { constructor(original: LocalModule) : this( @@ -41,9 +47,12 @@ data class LocalModuleEntity( lastUpdated = lastUpdated ) - @Entity(tableName = "local_updatable") + @Entity( + tableName = "local_updatable", + primaryKeys = ["id"] + ) data class Updatable( - @PrimaryKey val id: String, + 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 b6b0cb72..f1affed1 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 @@ -1,61 +1,60 @@ package dev.sanmer.mrepo.database.entity +import androidx.room.ColumnInfo import androidx.room.Embedded import androidx.room.Entity import dev.sanmer.mrepo.model.online.OnlineModule -import dev.sanmer.mrepo.model.online.TrackJson +import dev.sanmer.mrepo.model.online.VersionItem @Entity( tableName = "online", - primaryKeys = ["id", "repoUrl"] + primaryKeys = ["id", "repo_url"] ) data class OnlineModuleEntity( - val id: String, + @ColumnInfo(name = "repo_url") val repoUrl: String, + val id: String, val name: String, val version: String, + @ColumnInfo(name = "version_code") val versionCode: Int, val author: String, val description: String, - @Embedded val track: Track + @Embedded val metadata: Metadata ) { constructor( - original: OnlineModule, - repoUrl: String + repoUrl: String, + original: OnlineModule ) : this( - id = original.id, repoUrl = repoUrl, + id = original.id, name = original.name, version = original.version, versionCode = original.versionCode, author = original.author, description = original.description, - track = Track(original.track) + metadata = Metadata(original.metadata) ) - fun toModule() = OnlineModule( + fun toJson(versions: List = emptyList()) = OnlineModule( id = id, name = name, version = version, versionCode = versionCode, author = author, description = description, - track = track.toTrack(), - versions = listOf() + metadata = metadata.toJson(), + versions = versions ) - data class Track( - val type: String, - val added: Float, - val license: String, - val homepage: String, - val source: String, - val support: String, - val donate: String + data class Metadata( + val license: String = "", + val homepage: String = "", + val source: String = "", + val donate: String = "", + val support: String = "" ) { - constructor(original: TrackJson) : this( - type = original.type.name, - added = original.added, + constructor(original: OnlineModule.Metadata) : this( license = original.license, homepage = original.homepage, source = original.source, @@ -63,9 +62,7 @@ data class OnlineModuleEntity( donate = original.donate ) - fun toTrack() = TrackJson( - typeName = type, - added = added, + fun toJson() = OnlineModule.Metadata( license = license, homepage = homepage, source = source, 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 e571f9b2..cb4da9e8 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 @@ -2,52 +2,46 @@ package dev.sanmer.mrepo.database.entity import androidx.room.Embedded import androidx.room.Entity -import androidx.room.PrimaryKey import dev.sanmer.mrepo.model.online.ModulesJson -@Entity(tableName = "repo") +@Entity( + tableName = "repo", + primaryKeys = ["url"] +) data class RepoEntity( - @PrimaryKey val url: String, + val url: String, + val disable: Boolean, + val size: Int, val name: String, - val enable: Boolean, + val timestamp: Long, @Embedded val metadata: Metadata ) { constructor(url: String) : this( url = url, + disable = false, + size = 0, name = url, - enable = true, - metadata = Metadata.default() + timestamp = 0L, + metadata = Metadata() ) - override fun equals(other: Any?): Boolean { - return when (other) { - is RepoEntity -> url == other.url - else -> false - } - } - - override fun hashCode(): Int { - return url.hashCode() - } - fun copy(modulesJson: ModulesJson) = copy( + size = modulesJson.modules.size, name = modulesJson.name, - metadata = Metadata( - timestamp = modulesJson.metadata.timestamp, - size = modulesJson.modules.size - ) + timestamp = modulesJson.timestamp, + metadata = Metadata(modulesJson.metadata) ) data class Metadata( - val timestamp: Float, - val size: Int + val homepage: String = "", + val donate: String = "", + val support: String = "" ) { - companion object { - fun default() = Metadata( - timestamp = 0f, - size = 0 - ) - } + constructor(original: ModulesJson.Metadata) : this( + homepage = original.homepage, + donate = original.donate, + support = original.support + ) } companion object { 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 36f82910..120df5c9 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 @@ -1,28 +1,32 @@ package dev.sanmer.mrepo.database.entity +import androidx.room.ColumnInfo import androidx.room.Entity import dev.sanmer.mrepo.model.online.VersionItem @Entity( tableName = "version", - primaryKeys = ["id", "repoUrl", "versionCode"] + primaryKeys = ["id", "repo_url", "version_code"] ) data class VersionItemEntity( - val id: String, + @ColumnInfo(name = "repo_url") val repoUrl: String, - val timestamp: Float, + val id: String, + val timestamp: Long, val version: String, + @ColumnInfo(name = "version_code") val versionCode: Int, + @ColumnInfo(name = "zip_url") val zipUrl: String, val changelog: String ) { constructor( - original: VersionItem, + repoUrl: String, id: String, - repoUrl: String + original: VersionItem, ) : this( - id = id, repoUrl= repoUrl, + id = id, timestamp = original.timestamp, version = original.version, versionCode = original.versionCode, @@ -30,7 +34,7 @@ data class VersionItemEntity( changelog = original.changelog ) - fun toItem() = VersionItem( + fun toJson() = VersionItem( repoUrl= repoUrl, timestamp = timestamp, version = version, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/model/json/UpdateJson.kt b/app/src/main/kotlin/dev/sanmer/mrepo/model/json/UpdateJson.kt index ce5d3099..b1a2059e 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/json/UpdateJson.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/model/json/UpdateJson.kt @@ -5,6 +5,7 @@ import com.squareup.moshi.Moshi import com.squareup.moshi.adapter import dev.sanmer.mrepo.compat.NetworkCompat import dev.sanmer.mrepo.model.online.VersionItem +import dev.sanmer.mrepo.utils.Utils @JsonClass(generateAdapter = true) data class UpdateJson( @@ -13,7 +14,7 @@ data class UpdateJson( val zipUrl: String, val changelog: String ) { - fun toItemOrNull(timestamp: Float): VersionItem? { + fun toItemOrNull(timestamp: Long): VersionItem? { if (!NetworkCompat.isUrl(zipUrl)) return null val changelog = when { @@ -24,7 +25,7 @@ data class UpdateJson( return VersionItem( timestamp = timestamp, - version = version, + version = Utils.getVersionDisplay(version, versionCode), versionCode = versionCode, zipUrl = zipUrl, changelog = changelog @@ -48,7 +49,7 @@ data class UpdateJson( val (json, headers) = result.getOrThrow() json?.let { val lastModified = headers.getInstant("Last-Modified")?.toEpochMilli() - val timestamp = (lastModified ?: System.currentTimeMillis()) / 1000f + val timestamp = lastModified ?: System.currentTimeMillis() json.toItemOrNull(timestamp) } } 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 54864116..213f773f 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,17 +5,14 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class ModulesJson( val name: String, - val metadata: Metadata = Metadata.default(), + val timestamp: Long, + val metadata: Metadata = Metadata(), val modules: List ) { @JsonClass(generateAdapter = true) data class Metadata( - val timestamp: Float - ) { - companion object { - fun default() = Metadata( - timestamp = 0f - ) - } - } + val homepage: String = "", + val donate: String = "", + val support: String = "" + ) } \ 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 241facc6..66814558 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 @@ -1,17 +1,19 @@ package dev.sanmer.mrepo.model.online -import dev.sanmer.mrepo.utils.Utils +import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import dev.sanmer.mrepo.utils.Utils @JsonClass(generateAdapter = true) data class OnlineModule( val id: String, val name: String, val version: String, + @Json(name = "version_code") val versionCode: Int, val author: String, val description: String, - val track: TrackJson, + val metadata: Metadata = Metadata(), val versions: List, ) { val versionDisplay by lazy { @@ -29,6 +31,15 @@ data class OnlineModule( return id.hashCode() } + @JsonClass(generateAdapter = true) + data class Metadata( + val license: String = "", + val homepage: String = "", + val source: String = "", + val donate: String = "", + val support: String = "" + ) + companion object { fun example() = OnlineModule( id = "online_example", @@ -37,9 +48,7 @@ data class OnlineModule( versionCode = 1703, author = "Sanmer", description = "This is an example!", - track = TrackJson( - typeName = "ONLINE_JSON", - added = 0f, + metadata = Metadata( license = "GPL-3.0" ), versions = emptyList() 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 deleted file mode 100644 index 6a31cc2d..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/model/online/TrackJson.kt +++ /dev/null @@ -1,31 +0,0 @@ -package dev.sanmer.mrepo.model.online - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class TrackJson( - @Json(name = "type") - val typeName: String, - val added: Float, - val license: String = "", - val homepage: String = "", - val source: String = "", - val support: String = "", - val donate: String = "" -) { - val type = Type.valueOf(typeName) - - 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 ae412544..1aba10f8 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 @@ -1,19 +1,17 @@ package dev.sanmer.mrepo.model.online -import dev.sanmer.mrepo.utils.Utils import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class VersionItem( - @Json(ignore = true) val repoUrl: String = "", - val timestamp: Float, + @Json(ignore = true) + val repoUrl: String = "", + val timestamp: Long, val version: String, + @Json(name = "version_code") val versionCode: Int, + @Json(name = "zip_url") val zipUrl: String, val changelog: String -) { - val versionDisplay by lazy { - Utils.getVersionDisplay(version, versionCode) - } -} \ No newline at end of file +) \ 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 22951f79..65861aa6 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt @@ -11,7 +11,6 @@ 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 -import dev.sanmer.mrepo.utils.extensions.merge import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext @@ -26,16 +25,30 @@ class LocalRepository @Inject constructor( private val localDao: LocalDao, private val joinDao: JoinDao ) { - fun getLocalAllAsFlow() = localDao.getAllAsFlow().map { list -> - list.map { it.toModule() } + fun getLocalAllAsFlow() = localDao.getAllAsFlow().map { data -> + data.map { it.toModule() } } + fun getLocalWithUpdatableAllAsFlow() = joinDao.getLocalWithUpdatableAll() + .map { entries -> + entries.map { + val module = it.key.toModule() + val updatable = it.value?.updatable ?: true + module to updatable + } + } + suspend fun getLocalAll() = withContext(Dispatchers.IO) { localDao.getAll().map { it.toModule() } } - suspend fun getLocalByIdOrNull(id: String) = withContext(Dispatchers.IO) { - localDao.getByIdOrNull(id)?.toModule() + suspend fun getLocalWithUpdatableOrNull(id: String) = withContext(Dispatchers.IO) { + joinDao.getLocalWithUpdatable(id) + .map { + val module = it.key.toModule() + val updatable = it.value?.updatable ?: true + module to updatable + }.firstOrNull() } suspend fun insertLocal(value: LocalModule) = withContext(Dispatchers.IO) { @@ -54,26 +67,20 @@ class LocalRepository @Inject constructor( localDao.deleteAll() } - suspend fun insertUpdatableTag(id: String, updatable: Boolean) = withContext(Dispatchers.IO) { - localDao.insertUpdatableTag( - LocalModuleEntity.Updatable( - id = id, - updatable = updatable - ) + suspend fun insertLocalUpdatable(id: String, updatable: Boolean) = withContext(Dispatchers.IO) { + localDao.insertUpdatable( + LocalModuleEntity.Updatable(id = id, updatable = updatable) ) } - suspend fun hasUpdatableTag(id: String) = withContext(Dispatchers.IO) { - localDao.hasUpdatableTagOrNull(id)?.updatable ?: true + suspend fun isLocalUpdatable(id: String) = withContext(Dispatchers.IO) { + localDao.getUpdatableOrNull(id)?.updatable ?: true } - suspend fun clearUpdatableTag(removed: List) = withContext(Dispatchers.IO) { - localDao.deleteUpdatableTag( + suspend fun deleteLocalUpdatable(removed: List) = withContext(Dispatchers.IO) { + localDao.deleteUpdatable( removed.map { - LocalModuleEntity.Updatable( - id = it.id, - updatable = false - ) + LocalModuleEntity.Updatable(id = it.id, updatable = false) } ) } @@ -84,10 +91,6 @@ class LocalRepository @Inject constructor( repoDao.getAll() } - suspend fun getRepoByUrl(url: String) = withContext(Dispatchers.IO) { - repoDao.getByUrl(url) - } - suspend fun insertRepo(value: RepoEntity) = withContext(Dispatchers.IO) { repoDao.insert(value) } @@ -96,50 +99,27 @@ class LocalRepository @Inject constructor( repoDao.delete(value) } - fun getOnlineAllAsFlow() = joinDao.getOnlineAllAsFlow().map { list -> - val modules = mutableListOf() - list.forEach { entity -> - val new = entity.toModule() - if (modules.contains(new)) { - val old = modules.first { it.id == new.id } - if (new.versionCode > old.versionCode) { - modules.remove(old) - modules.add(new.copy(versions = old.versions)) - } - } else { - val versions = getVersionById(new.id) - modules.add(new.copy(versions = versions)) - } + fun getOnlineAllAsFlow() = joinDao.getOnlineAllAsFlow().map { entries -> + entries.map { (module, versions) -> + module.toJson( + versions = versions.map { it.toJson() } + ) } - - modules - } - - suspend fun getOnlineByIdAndUrl(id: String, repoUrl: String) = withContext(Dispatchers.IO) { - joinDao.getOnlineByIdAndUrl(id, repoUrl).toModule() } suspend fun getOnlineAllById(id: String) = withContext(Dispatchers.IO) { - onlineDao.getAllById(id).map { it.toModule() } + onlineDao.getAllById(id).map { it.toJson() } } - suspend fun insertOnline(list: List, repoUrl: String) = withContext(Dispatchers.IO) { + suspend fun insertOnline(repoUrl: String, list: List) = withContext(Dispatchers.IO) { val modules = list.map { - OnlineModuleEntity( - original = it, - repoUrl = repoUrl - ) + OnlineModuleEntity(repoUrl = repoUrl, original = it) } - val versions = list.map { module -> module.versions.map { - VersionItemEntity( - original = it, - id = module.id, - repoUrl = repoUrl - ) + VersionItemEntity(repoUrl = repoUrl, id = module.id, original = it) } - }.merge() + }.flatten() versionDao.insert(versions) onlineDao.insert(modules) @@ -151,6 +131,14 @@ class LocalRepository @Inject constructor( } suspend fun getVersionById(id: String) = withContext(Dispatchers.IO) { - joinDao.getVersionById(id).map { it.toItem() } + joinDao.getVersionWithRepo(id).values.flatMap { versions -> + versions.map { it.toJson() } + } + } + + suspend fun getVersionByIdWithRepo(id: String) = withContext(Dispatchers.IO) { + joinDao.getVersionWithRepo(id).mapValues { entry -> + entry.value.map { it.toJson() } + } } } \ No newline at end of file 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 b9de6248..c4b26262 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt @@ -18,39 +18,46 @@ class ModulesRepository @Inject constructor( suspend fun getLocalAll() = withContext(Dispatchers.IO) { runCatching { - val modules = mm.modules - localRepository.insertLocal(modules) - + mm.modules.toList() + }.onSuccess { modules -> + val moduleIds = modules.map { it.id } val locals = localRepository.getLocalAll() - val removed = locals.filter { !modules.contains(it) } + val removed = locals.filter { !moduleIds.contains(it.id) } + localRepository.deleteLocal(removed) - localRepository.clearUpdatableTag(removed) + localRepository.deleteLocalUpdatable(removed) + localRepository.insertLocal(modules) + }.onFailure { + Timber.e(it, "getLocalAll") } } suspend fun getLocal(id: String) = withContext(Dispatchers.IO) { - val module = mm.getModuleById(id) - localRepository.insertLocal(module) + runCatching { + mm.getModuleById(id) + }.onSuccess { + localRepository.insertLocal(it) + }.onFailure { + Timber.e(it, "getLocal: $id") + } } suspend fun getRepoAll(onlyEnable: Boolean = true) = localRepository.getRepoAll().filter { - if (onlyEnable) it.enable else true + if (onlyEnable) !it.disable else true }.map { getRepo(it) } - suspend fun getRepo(repo: RepoEntity) = runRequest { - val api = IRepoManager.build(repo.url) - api.modules.execute() - }.onSuccess { modulesJson -> - localRepository.insertRepo(repo.copy(modulesJson)) - localRepository.deleteOnlineByUrl(repo.url) - localRepository.insertOnline( - list = modulesJson.modules, - repoUrl = repo.url - ) - }.onFailure { - Timber.e(it, "getRepo: ${repo.url}") - } + suspend fun getRepo(repo: RepoEntity) = + runRequest { + val api = IRepoManager.build(repo.url) + api.modules.execute() + }.onSuccess { modulesJson -> + localRepository.insertRepo(repo.copy(modulesJson)) + localRepository.deleteOnlineByUrl(repo.url) + localRepository.insertOnline(repoUrl = repo.url, list = modulesJson.modules) + }.onFailure { + Timber.e(it, "getRepo: ${repo.url}") + } } \ No newline at end of file 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 375b1df1..86c45ffa 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 @@ -88,10 +88,7 @@ fun ModuleItem( if (menu.showUpdatedTime) { Spacer(modifier = Modifier.height(2.dp)) Text( - text = stringResource( - id = R.string.module_update_at, - state.lastUpdated.toDate() - ), + text = stringResource(id = R.string.module_update_at, state.lastUpdated.toDate()), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline ) @@ -103,20 +100,19 @@ fun ModuleItem( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(2.dp) ) { - if (menu.showLicense && module.track.hasLicense) { - LabelItem(text = module.track.license) + if (menu.showLicense) { + LabelItem(text = module.metadata.license) } when { - state.updatable -> - LabelItem( - text = stringResource(id = R.string.module_new), - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError - ) - - state.installed -> - LabelItem(text = stringResource(id = R.string.module_installed)) + state.updatable -> LabelItem( + text = stringResource(id = R.string.module_new), + containerColor = MaterialTheme.colorScheme.error, + contentColor = MaterialTheme.colorScheme.onError + ) + state.installed -> LabelItem( + text = stringResource(id = R.string.module_installed) + ) } } } diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewScreen.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewScreen.kt index 2861f950..c1b81a11 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewScreen.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewScreen.kt @@ -32,7 +32,6 @@ fun ViewScreen( topBar = { ViewTopBar( online = viewModel.online, - tracks = viewModel.tracks, scrollBehavior = scrollBehavior, navController = navController ) 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 02fdaef5..643eabe3 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 @@ -23,22 +23,18 @@ 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.RepoEntity import dev.sanmer.mrepo.model.online.OnlineModule -import dev.sanmer.mrepo.model.online.TrackJson import dev.sanmer.mrepo.ui.component.CollapsingTopAppBar import dev.sanmer.mrepo.ui.component.CollapsingTopAppBarDefaults import dev.sanmer.mrepo.ui.component.Logo import dev.sanmer.mrepo.ui.providable.LocalUserPreferences import dev.sanmer.mrepo.ui.screens.repository.view.items.LicenseItem import dev.sanmer.mrepo.ui.screens.repository.view.items.TagItem -import dev.sanmer.mrepo.ui.screens.repository.view.items.TrackItem import dev.sanmer.mrepo.utils.extensions.openUrl @Composable fun ViewTopBar( online: OnlineModule, - tracks: List>, scrollBehavior: TopAppBarScrollBehavior, navController: NavController ) = CollapsingTopAppBar( @@ -52,8 +48,7 @@ fun ViewTopBar( }, content = { TopBarContent( - module = online, - tracks = tracks + module = online ) }, navigationIcon = { @@ -74,15 +69,14 @@ fun ViewTopBar( @Composable private fun TopBarContent( - module: OnlineModule, - tracks: List> + module: OnlineModule ) { val userPreferences = LocalUserPreferences.current val repositoryMenu = userPreferences.repositoryMenu val context = LocalContext.current - val hasLicense = module.track.hasLicense - val hasDonate = module.track.donate.isNotBlank() + val hasLicense = module.metadata.license.isNotBlank() + val hasDonate = module.metadata.donate.isNotBlank() Row( modifier = Modifier.padding(horizontal = 16.dp), @@ -122,7 +116,7 @@ private fun TopBarContent( append("ID = ${module.id}") if (hasLicense) { append(", ") - append("License = ${module.track.license}") + append("License = ${module.metadata.license}") } }, style = MaterialTheme.typography.labelSmall, @@ -138,20 +132,16 @@ private fun TopBarContent( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - TrackItem( - tracks = tracks - ) - if (hasLicense) { LicenseItem( - licenseId = module.track.license + licenseId = module.metadata.license ) } if (hasDonate) { TagItem( icon = R.drawable.currency_dollar, - onClick = { context.openUrl(module.track.donate) } + onClick = { context.openUrl(module.metadata.donate) } ) } } 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 deleted file mode 100644 index 2e8436ad..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TrackItem.kt +++ /dev/null @@ -1,135 +0,0 @@ -package dev.sanmer.mrepo.ui.screens.repository.view.items - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBars -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.BottomSheetDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -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.RepoEntity -import dev.sanmer.mrepo.model.online.TrackJson -import dev.sanmer.mrepo.ui.utils.expandedShape -import dev.sanmer.mrepo.utils.extensions.toDateTime - -@Composable -fun TrackItem( - tracks: List> -) = Box { - var open by rememberSaveable { mutableStateOf(false) } - - TagItem( - icon = R.drawable.tag, - onClick = { open = true } - ) - - if (open) { - ModalBottomSheet( - onDismissRequest = { open = false }, - shape = BottomSheetDefaults.expandedShape(15.dp), - windowInsets = WindowInsets.navigationBars - ) { - Text( - text = stringResource(id = R.string.view_module_view_track), - style = MaterialTheme.typography.headlineSmall, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) - - LazyColumn( - modifier = Modifier - .padding(all = 16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - items( - items = tracks, - key = { it.first.url } - ) { (repo, track) -> - ValueItem( - repo = repo, - track = track - ) - } - } - } - } -} - -@Composable -private fun ValueItem( - repo: RepoEntity, - track: TrackJson -) = Surface( - modifier = Modifier.fillMaxWidth(), - tonalElevation = 6.dp, - border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline), - shape = RoundedCornerShape(15.dp) -) { - Row( - modifier = Modifier.padding(all = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(30.dp), - painter = painterResource(id = R.drawable.code_asterix), - contentDescription = null, - tint = MaterialTheme.colorScheme.onSurfaceVariant - ) - - Column( - modifier = Modifier - .padding(start = 16.dp) - .fillMaxWidth() - ) { - Text( - text = repo.name, - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.primary - ) - - Spacer(modifier = Modifier.height(8.dp)) - - Text( - text = stringResource(id = R.string.view_module_type, - track.type.name.replace("_", " ")), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.outline - ) - - stringResource(id = R.string.view_module_added, - track.added.toDateTime() - ) - - Text( - text = stringResource(id = R.string.view_module_added, - track.added.toDateTime()), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.outline - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt index 515c64b1..e940f778 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt @@ -38,19 +38,19 @@ fun AboutPage( ) { ValueItem( key = stringResource(id = R.string.view_module_homepage), - value = online.track.homepage, + value = online.metadata.homepage, icon = R.drawable.world_www ) ValueItem( key = stringResource(id = R.string.view_module_source), - value = online.track.source, + value = online.metadata.source, icon = R.drawable.brand_git ) ValueItem( key = stringResource(id = R.string.view_module_support), - value = online.track.support, + value = online.metadata.support, icon = R.drawable.heart_handshake ) } 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 e163d1e6..ece45240 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 @@ -119,7 +119,7 @@ private fun CloudItem( ) { ValueItem( key = stringResource(id = R.string.view_module_version), - value = item.versionDisplay, + value = item.version, modifier = Modifier.weight(1f) ) @@ -139,7 +139,7 @@ private fun CloudItem( ValueItem( key = stringResource(id = R.string.view_module_last_updated), - value = item.timestamp.toDateTime() + value = item.timestamp.toDateTime().toString() ) } @@ -204,7 +204,7 @@ private fun LocalItem( if (local.lastUpdated != 0L) { ValueItem( key = stringResource(id = R.string.view_module_last_updated), - value = local.lastUpdated.toDateTime() + value = local.lastUpdated.toDateTime().toString() ) } } 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 dd3505b4..1adeaef6 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 @@ -109,7 +109,7 @@ private fun VersionItem( verticalAlignment = Alignment.CenterVertically ) { Text( - text = item.versionDisplay, + text = item.version, style = MaterialTheme.typography.bodyMedium ) @@ -130,7 +130,7 @@ private fun VersionItem( } Text( - text = item.timestamp.toDate(), + text = item.timestamp.toDate().toString(), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline ) 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 85ceb22b..f468b58d 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 @@ -19,15 +19,15 @@ 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.viewmodel.RepositoriesViewModel.RepoState +import dev.sanmer.mrepo.database.entity.RepoEntity @Composable fun RepositoriesList( - list: List, + list: List, state: LazyListState, - insert: (RepoState) -> Unit, - delete: (RepoState) -> Unit, - update: (RepoState) -> Unit + insert: (RepoEntity) -> Unit, + delete: (RepoEntity) -> Unit, + update: (RepoEntity) -> Unit ) = LazyColumn( state = state, modifier = Modifier.fillMaxSize(), @@ -49,10 +49,10 @@ fun RepositoriesList( @Composable private fun RepositoryItem( - repo: RepoState, - toggle: (RepoState) -> Unit, - onUpdate: (RepoState) -> Unit, - onDelete: (RepoState) -> Unit, + repo: RepoEntity, + toggle: (RepoEntity) -> Unit, + onUpdate: (RepoEntity) -> Unit, + onDelete: (RepoEntity) -> Unit, ) { var delete by remember { mutableStateOf(false) } if (delete) DeleteDialog( @@ -63,7 +63,7 @@ private fun RepositoryItem( RepositoryItem( repo = repo, - toggle = { toggle(repo.copy(enable = it)) }, + toggle = { toggle(repo.copy(disable = it)) }, update = { onUpdate(repo) }, delete = { delete = true } ) @@ -71,7 +71,7 @@ private fun RepositoryItem( @Composable private fun DeleteDialog( - repo: RepoState, + repo: RepoEntity, onClose: () -> Unit, onConfirm: () -> Unit ) = AlertDialog( 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 3e8b3353..13baa865 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 @@ -39,15 +39,15 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R +import dev.sanmer.mrepo.database.entity.RepoEntity import dev.sanmer.mrepo.ui.component.LabelItem 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( - repo: RepoState, + repo: RepoEntity, toggle: (Boolean) -> Unit, update: () -> Unit, delete: () -> Unit, @@ -55,7 +55,7 @@ fun RepositoryItem( shape = RoundedCornerShape(15.dp), color = MaterialTheme.colorScheme.surface, tonalElevation = 1.dp, - onClick = { toggle(!repo.enable) }, + onClick = { toggle(!repo.disable) }, ) { Column( modifier = Modifier @@ -67,10 +67,10 @@ fun RepositoryItem( ) { Icon( modifier = Modifier.size(32.dp), - painter = painterResource(id = if (repo.enable) { - R.drawable.circle_check_filled - } else { + painter = painterResource(id = if (repo.disable) { R.drawable.circle_x_filled + } else { + R.drawable.circle_check_filled }), contentDescription = null, tint = MaterialTheme.colorScheme.secondary @@ -80,7 +80,7 @@ fun RepositoryItem( Column( modifier = Modifier .weight(1f) - .alpha(if (repo.enable) 1f else 0.5f), + .alpha(if (repo.disable) 0.5f else 1f), verticalArrangement = Arrangement.spacedBy(2.dp) ) { Text( @@ -136,7 +136,7 @@ fun RepositoryItem( @Composable private fun BottomSheet( - repo: RepoState, + repo: RepoEntity, onDelete: () -> Unit, onClose: () -> Unit ) = ModalBottomSheet( @@ -169,8 +169,7 @@ private fun BottomSheet( ) Text( - text = stringResource(id = R.string.module_update_at, - repo.timestamp.toDateTime()), + text = stringResource(id = R.string.module_update_at, repo.timestamp.toDateTime()), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline ) diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ListExt.kt b/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ListExt.kt deleted file mode 100644 index f9f35ac7..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ListExt.kt +++ /dev/null @@ -1,7 +0,0 @@ -package dev.sanmer.mrepo.utils.extensions - -inline fun List>.merge(): List { - val values = mutableListOf() - forEach { values.addAll(it) } - return values -} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocalDateTimeExt.kt b/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocalDateTimeExt.kt index 95b4fae6..bc7e94a0 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocalDateTimeExt.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocalDateTimeExt.kt @@ -2,28 +2,19 @@ package dev.sanmer.mrepo.utils.extensions import kotlinx.datetime.Clock import kotlinx.datetime.Instant +import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime import kotlinx.datetime.TimeZone import kotlinx.datetime.toLocalDateTime -fun Float.toDateTime(): String { - val instant = Instant.fromEpochMilliseconds(times(1000).toLong()) - return instant.toLocalDateTime(TimeZone.currentSystemDefault()).toString() -} - -fun Float.toDate(): String { - val instant = Instant.fromEpochMilliseconds(times(1000).toLong()) - return instant.toLocalDateTime(TimeZone.currentSystemDefault()).date.toString() -} - -fun Long.toDateTime(): String { +fun Long.toDateTime(): LocalDateTime { val instant = Instant.fromEpochMilliseconds(this) - return instant.toLocalDateTime(TimeZone.currentSystemDefault()).toString() + return instant.toLocalDateTime(TimeZone.currentSystemDefault()) } -fun Long.toDate(): String { +fun Long.toDate(): LocalDate { val instant = Instant.fromEpochMilliseconds(this) - return instant.toLocalDateTime(TimeZone.currentSystemDefault()).date.toString() + return instant.toLocalDateTime(TimeZone.currentSystemDefault()).date } fun LocalDateTime.Companion.now() = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()) \ No newline at end of file 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 bafb2662..d86846b8 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt @@ -16,7 +16,6 @@ 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 -import dev.sanmer.mrepo.model.online.TrackJson import dev.sanmer.mrepo.model.online.VersionItem import dev.sanmer.mrepo.repository.LocalRepository import dev.sanmer.mrepo.repository.UserPreferencesRepository @@ -45,9 +44,9 @@ class ModuleViewModel @Inject constructor( versions.firstOrNull()?.second } - val isEmptyAbout get() = online.track.homepage.isBlank() - && online.track.source.isBlank() - && online.track.support.isBlank() + val isEmptyAbout get() = online.metadata.homepage.isBlank() + && online.metadata.source.isBlank() + && online.metadata.support.isBlank() var local: LocalModule? by mutableStateOf(null) private set @@ -63,7 +62,6 @@ class ModuleViewModel @Inject constructor( } val versions = mutableStateListOf>() - val tracks = mutableStateListOf>() init { Timber.d("ModuleViewModel init: $moduleId") @@ -75,23 +73,16 @@ class ModuleViewModel @Inject constructor( online = it } - localRepository.getLocalByIdOrNull(moduleId)?.let { - local = it - notifyUpdates = localRepository.hasUpdatableTag(moduleId) + localRepository.getLocalWithUpdatableOrNull(moduleId)?.let { (module, update) -> + local = module + notifyUpdates = update } - localRepository.getVersionById(moduleId).forEach { - val repo = localRepository.getRepoByUrl(it.repoUrl) - - val item = repo to it - val track = repo to localRepository.getOnlineByIdAndUrl( - id = online.id, - repoUrl = it.repoUrl - ).track - - versions.add(item) - if (track !in tracks) tracks.add(track) - } + versions.addAll( + localRepository.getVersionByIdWithRepo(moduleId).flatMap { entry -> + entry.value.map { entry.key to it } + }.sortedByDescending { it.second.versionCode } + ) if (installed) { UpdateJson.load(local!!.updateJson)?.let { @@ -103,7 +94,7 @@ class ModuleViewModel @Inject constructor( fun setUpdatesTag(updatable: Boolean) { viewModelScope.launch { notifyUpdates = updatable - localRepository.insertUpdatableTag(moduleId, updatable) + localRepository.insertLocalUpdatable(moduleId, updatable) } } @@ -113,8 +104,8 @@ class ModuleViewModel @Inject constructor( install: Boolean ) { viewModelScope.launch { - val downloadPath = userPreferencesRepository.data - .first().downloadPath + val userPreferences = userPreferencesRepository.data.first() + val downloadPath = userPreferences.downloadPath val filename = Utils.getFilename( name = online.name, @@ -128,7 +119,7 @@ class ModuleViewModel @Inject constructor( url = item.zipUrl, filename = filename, title = online.name, - desc = item.versionDisplay + desc = item.version ) val listener = object : DownloadService.IDownloadListener { diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt index f704f181..bc41808e 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt @@ -215,19 +215,19 @@ class ModulesViewModel @Inject constructor( fun getVersionItem(module: LocalModule): VersionItem? { viewModelScope.launch { - if (versionItems.containsKey(module.id)) { + if (!localRepository.isLocalUpdatable(module.id)) { + versionItems.remove(module.id) return@launch } - if (!localRepository.hasUpdatableTag(module.id)) { - versionItems.remove(module.id) + if (versionItems.containsKey(module.id)) { return@launch } val versionItem = if (module.updateJson.isNotBlank()) { UpdateJson.load(module.updateJson) } else { - localRepository.getVersionById(module.id).firstOrNull() + localRepository.getVersionById(module.id).maxByOrNull { it.versionCode } } versionItems[module.id] = versionItem @@ -258,7 +258,7 @@ class ModulesViewModel @Inject constructor( url = item.zipUrl, filename = filename, title = module.name, - desc = item.versionDisplay + desc = item.version ) val listener = object : DownloadService.IDownloadListener { 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 bda09135..076913f3 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt @@ -1,6 +1,5 @@ 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 @@ -24,7 +23,7 @@ class RepositoriesViewModel @Inject constructor( private val localRepository: LocalRepository, private val modulesRepository: ModulesRepository ) : ViewModel() { - private val reposFlow = MutableStateFlow(listOf()) + private val reposFlow = MutableStateFlow(listOf()) val repos get() = reposFlow.asStateFlow() var isLoading by mutableStateOf(true) @@ -45,8 +44,7 @@ class RepositoriesViewModel @Inject constructor( private fun dataObserver() { localRepository.getRepoAllAsFlow() .onEach { list -> - reposFlow.value = list.map { RepoState(it) } - .sortedBy { it.name } + reposFlow.value = list.sortedBy { it.name } isLoading = false @@ -68,26 +66,26 @@ class RepositoriesViewModel @Inject constructor( } } - fun insert(repo: RepoState) { + fun insert(repo: RepoEntity) { viewModelScope.launch { - localRepository.insertRepo(repo.toRepo()) + localRepository.insertRepo(repo) } } - fun delete(repo: RepoState) { + fun delete(repo: RepoEntity) { viewModelScope.launch { - localRepository.deleteRepo(repo.toRepo()) + localRepository.deleteRepo(repo) localRepository.deleteOnlineByUrl(repo.url) } } fun update( - repo: RepoState, + repo: RepoEntity, onFailure: (Throwable) -> Unit ) { viewModelScope.launch { refreshing { - modulesRepository.getRepo(repo.toRepo()) + modulesRepository.getRepo(repo) .onFailure { Timber.e(it, "update: ${repo.url}") onFailure(it) @@ -103,31 +101,4 @@ class RepositoriesViewModel @Inject constructor( } } } - - @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 d98901eb..306615ac 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt @@ -59,13 +59,11 @@ class RepositoryViewModel @Inject constructor( private fun dataObserver() { combine( localRepository.getOnlineAllAsFlow(), + localRepository.getLocalWithUpdatableAllAsFlow(), repositoryMenu - ) { list, menu -> - cacheFlow.value = list.map { - it.createState( - local = localRepository.getLocalByIdOrNull(it.id), - hasUpdatableTag = localRepository.hasUpdatableTag(it.id) - ) to it + ) { online, local, menu -> + cacheFlow.value = online.map { + createOnlineState(it, local) }.sortedWith( comparator(menu.option, menu.descending) ).let { v -> @@ -143,25 +141,26 @@ class RepositoryViewModel @Inject constructor( } } - 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 + private suspend fun createOnlineState( + online: OnlineModule, + locals: List> + ): Pair { + var installed = false + var updatable = false + + locals.firstOrNull { it.first.id == online.id }?.let { (local, isUpdatable) -> + installed = local.author == online.author + updatable = (local.versionCode < online.versionCode) && isUpdatable } - return OnlineState( + val state = OnlineState( installed = installed, updatable = updatable, - hasLicense = track.license.isNotBlank(), - lastUpdated = versions.firstOrNull()?.timestamp ?: 1.47333965E9f + hasLicense = online.metadata.license.isNotBlank(), + lastUpdated = online.versions.firstOrNull()?.timestamp ?: 0L ) + + return state to online } @Immutable @@ -169,14 +168,14 @@ class RepositoryViewModel @Inject constructor( val installed: Boolean, val updatable: Boolean, val hasLicense: Boolean, - val lastUpdated: Float + val lastUpdated: Long ) { companion object { fun example() = OnlineState( installed = true, updatable = false, hasLicense = true, - lastUpdated = 1.66064064E9f + lastUpdated = 1660640640000L ) } } From 91190af1a19c04bad0bffe6e3585a63a6957959c Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 01:36:49 +0800 Subject: [PATCH 2/8] Revert "Override equals for `Module`" This reverts commit a619274bc77cca19d3029b6e87da0b79aa3ad9a3. --- .../main/kotlin/dev/sanmer/mrepo/content/Module.kt | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/core/src/main/kotlin/dev/sanmer/mrepo/content/Module.kt b/core/src/main/kotlin/dev/sanmer/mrepo/content/Module.kt index 7083339d..95709277 100644 --- a/core/src/main/kotlin/dev/sanmer/mrepo/content/Module.kt +++ b/core/src/main/kotlin/dev/sanmer/mrepo/content/Module.kt @@ -14,15 +14,4 @@ data class Module( val updateJson: String, val state: State, val lastUpdated: Long -) : Parcelable { - override fun equals(other: Any?): Boolean { - return when (other) { - is Module -> id == other.id - else -> false - } - } - - override fun hashCode(): Int { - return id.hashCode() - } -} \ No newline at end of file +) : Parcelable \ No newline at end of file From b114a8d198bffa5166b688710b3c558561b3236d Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 20:48:59 +0800 Subject: [PATCH 3/8] Optimize DAO for database --- .../1.json | 154 +++++++++--------- .../dev/sanmer/mrepo/database/AppDatabase.kt | 18 +- .../dev/sanmer/mrepo/database/dao/JoinDao.kt | 40 ----- .../dev/sanmer/mrepo/database/dao/LocalDao.kt | 55 ++++--- .../sanmer/mrepo/database/dao/OnlineDao.kt | 19 --- .../dev/sanmer/mrepo/database/dao/RepoDao.kt | 85 +++++++++- .../sanmer/mrepo/database/dao/VersionDao.kt | 16 -- .../mrepo/database/di/DatabaseModule.kt | 25 +-- .../{Local.kt => local/LocalModuleEntity.kt} | 2 +- .../OnlineModuleEntity.kt} | 2 +- .../entity/{Repo.kt => online/RepoEntity.kt} | 6 +- .../VersionItemEntity.kt} | 2 +- .../mrepo/repository/LocalRepository.kt | 153 +++++++---------- .../mrepo/repository/ModulesRepository.kt | 18 +- .../sanmer/mrepo/ui/activity/MainActivity.kt | 3 +- .../repository/view/pages/VersionsPage.kt | 2 +- .../settings/repositories/RepositoriesList.kt | 2 +- .../settings/repositories/RepositoryItem.kt | 2 +- .../mrepo/viewmodel/InstallViewModel.kt | 4 +- .../sanmer/mrepo/viewmodel/ModuleViewModel.kt | 15 +- .../mrepo/viewmodel/ModulesViewModel.kt | 2 +- .../mrepo/viewmodel/RepositoriesViewModel.kt | 6 +- .../mrepo/viewmodel/RepositoryViewModel.kt | 2 +- 23 files changed, 286 insertions(+), 347 deletions(-) delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/database/dao/JoinDao.kt delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/database/dao/OnlineDao.kt delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/database/dao/VersionDao.kt rename app/src/main/kotlin/dev/sanmer/mrepo/database/entity/{Local.kt => local/LocalModuleEntity.kt} (96%) rename app/src/main/kotlin/dev/sanmer/mrepo/database/entity/{Online.kt => online/OnlineModuleEntity.kt} (97%) rename app/src/main/kotlin/dev/sanmer/mrepo/database/entity/{Repo.kt => online/RepoEntity.kt} (89%) rename app/src/main/kotlin/dev/sanmer/mrepo/database/entity/{Version.kt => online/VersionItemEntity.kt} (95%) diff --git a/app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json b/app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json index 45686ecd..39aa1183 100644 --- a/app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json +++ b/app/schemas/dev.sanmer.mrepo.database.AppDatabase/1.json @@ -2,11 +2,11 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "b1bfea045a8aae2b31e57dcfb1f9a45c", + "identityHash": "d6e648e0e34c262d9de5c5d59368e3d8", "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`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `disable` INTEGER NOT NULL, `size` INTEGER NOT NULL, `name` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `homepage` TEXT NOT NULL, `donate` TEXT NOT NULL, `support` TEXT NOT NULL, PRIMARY KEY(`url`))", "fields": [ { "fieldPath": "url", @@ -15,60 +15,52 @@ "notNull": true }, { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", + "fieldPath": "disable", + "columnName": "disable", + "affinity": "INTEGER", "notNull": true }, { - "fieldPath": "enable", - "columnName": "enable", + "fieldPath": "size", + "columnName": "size", "affinity": "INTEGER", "notNull": true }, { - "fieldPath": "metadata.timestamp", - "columnName": "timestamp", - "affinity": "REAL", + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", "notNull": true }, { - "fieldPath": "metadata.size", - "columnName": "size", + "fieldPath": "timestamp", + "columnName": "timestamp", "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", + "fieldPath": "metadata.homepage", + "columnName": "homepage", "affinity": "TEXT", "notNull": true }, { - "fieldPath": "updatable", - "columnName": "updatable", - "affinity": "INTEGER", + "fieldPath": "metadata.donate", + "columnName": "donate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "metadata.support", + "columnName": "support", + "affinity": "TEXT", "notNull": true } ], "primaryKey": { "autoGenerate": false, "columnNames": [ - "id" + "url" ] }, "indices": [], @@ -76,17 +68,17 @@ }, { "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`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repo_url` TEXT NOT NULL, `id` TEXT NOT NULL, `name` TEXT NOT NULL, `version` TEXT NOT NULL, `version_code` INTEGER NOT NULL, `author` TEXT NOT NULL, `description` TEXT NOT NULL, `license` TEXT NOT NULL, `homepage` TEXT NOT NULL, `source` TEXT NOT NULL, `donate` TEXT NOT NULL, `support` TEXT NOT NULL, PRIMARY KEY(`id`, `repo_url`))", "fields": [ { - "fieldPath": "id", - "columnName": "id", + "fieldPath": "repoUrl", + "columnName": "repo_url", "affinity": "TEXT", "notNull": true }, { - "fieldPath": "repoUrl", - "columnName": "repoUrl", + "fieldPath": "id", + "columnName": "id", "affinity": "TEXT", "notNull": true }, @@ -104,7 +96,7 @@ }, { "fieldPath": "versionCode", - "columnName": "versionCode", + "columnName": "version_code", "affinity": "INTEGER", "notNull": true }, @@ -121,44 +113,32 @@ "notNull": true }, { - "fieldPath": "track.type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "track.added", - "columnName": "added", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "track.license", + "fieldPath": "metadata.license", "columnName": "license", "affinity": "TEXT", "notNull": true }, { - "fieldPath": "track.homepage", + "fieldPath": "metadata.homepage", "columnName": "homepage", "affinity": "TEXT", "notNull": true }, { - "fieldPath": "track.source", + "fieldPath": "metadata.source", "columnName": "source", "affinity": "TEXT", "notNull": true }, { - "fieldPath": "track.support", - "columnName": "support", + "fieldPath": "metadata.donate", + "columnName": "donate", "affinity": "TEXT", "notNull": true }, { - "fieldPath": "track.donate", - "columnName": "donate", + "fieldPath": "metadata.support", + "columnName": "support", "affinity": "TEXT", "notNull": true } @@ -167,7 +147,7 @@ "autoGenerate": false, "columnNames": [ "id", - "repoUrl" + "repo_url" ] }, "indices": [], @@ -175,24 +155,24 @@ }, { "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`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repo_url` TEXT NOT NULL, `id` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `version` TEXT NOT NULL, `version_code` INTEGER NOT NULL, `zip_url` TEXT NOT NULL, `changelog` TEXT NOT NULL, PRIMARY KEY(`id`, `repo_url`, `version_code`))", "fields": [ { - "fieldPath": "id", - "columnName": "id", + "fieldPath": "repoUrl", + "columnName": "repo_url", "affinity": "TEXT", "notNull": true }, { - "fieldPath": "repoUrl", - "columnName": "repoUrl", + "fieldPath": "id", + "columnName": "id", "affinity": "TEXT", "notNull": true }, { "fieldPath": "timestamp", "columnName": "timestamp", - "affinity": "REAL", + "affinity": "INTEGER", "notNull": true }, { @@ -203,13 +183,13 @@ }, { "fieldPath": "versionCode", - "columnName": "versionCode", + "columnName": "version_code", "affinity": "INTEGER", "notNull": true }, { "fieldPath": "zipUrl", - "columnName": "zipUrl", + "columnName": "zip_url", "affinity": "TEXT", "notNull": true }, @@ -224,8 +204,8 @@ "autoGenerate": false, "columnNames": [ "id", - "repoUrl", - "versionCode" + "repo_url", + "version_code" ] }, "indices": [], @@ -233,7 +213,7 @@ }, { "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`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `version` TEXT NOT NULL, `version_code` INTEGER NOT NULL, `author` TEXT NOT NULL, `description` TEXT NOT NULL, `state` TEXT NOT NULL, `update_json` TEXT NOT NULL, `last_updated` INTEGER NOT NULL, PRIMARY KEY(`id`))", "fields": [ { "fieldPath": "id", @@ -255,7 +235,7 @@ }, { "fieldPath": "versionCode", - "columnName": "versionCode", + "columnName": "version_code", "affinity": "INTEGER", "notNull": true }, @@ -279,13 +259,39 @@ }, { "fieldPath": "updateJson", - "columnName": "updateJson", + "columnName": "update_json", "affinity": "TEXT", "notNull": true }, { "fieldPath": "lastUpdated", - "columnName": "lastUpdated", + "columnName": "last_updated", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "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 } @@ -303,7 +309,7 @@ "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')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd6e648e0e34c262d9de5c5d59368e3d8')" ] } } \ 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 6d38b611..4ec42e8a 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/AppDatabase.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/AppDatabase.kt @@ -4,32 +4,26 @@ import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -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.OnlineModuleEntity -import dev.sanmer.mrepo.database.entity.RepoEntity -import dev.sanmer.mrepo.database.entity.VersionItemEntity +import dev.sanmer.mrepo.database.entity.local.LocalModuleEntity +import dev.sanmer.mrepo.database.entity.online.OnlineModuleEntity +import dev.sanmer.mrepo.database.entity.online.RepoEntity +import dev.sanmer.mrepo.database.entity.online.VersionItemEntity @Database( entities = [ RepoEntity::class, - LocalModuleEntity.Updatable::class, OnlineModuleEntity::class, VersionItemEntity::class, - LocalModuleEntity::class + LocalModuleEntity::class, + LocalModuleEntity.Updatable::class ], version = 1 ) abstract class AppDatabase : RoomDatabase() { abstract fun repoDao(): RepoDao - abstract fun onlineDao(): OnlineDao - abstract fun versionDao(): VersionDao abstract fun localDao(): LocalDao - abstract fun joinDao(): JoinDao companion object { fun build(context: Context) = 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 deleted file mode 100644 index 2a132b74..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/JoinDao.kt +++ /dev/null @@ -1,40 +0,0 @@ -package dev.sanmer.mrepo.database.dao - -import androidx.room.Dao -import androidx.room.Query -import dev.sanmer.mrepo.database.entity.LocalModuleEntity -import dev.sanmer.mrepo.database.entity.OnlineModuleEntity -import dev.sanmer.mrepo.database.entity.RepoEntity -import dev.sanmer.mrepo.database.entity.VersionItemEntity -import kotlinx.coroutines.flow.Flow - -@Dao -interface JoinDao { - @Query( - "SELECT * FROM local " + - "LEFT JOIN local_updatable ON local_updatable.id = local.id " - ) - fun getLocalWithUpdatableAll(): Flow> - - @Query( - "SELECT * FROM local " + - "LEFT JOIN local_updatable ON local_updatable.id = local.id " + - "WHERE local.id = :id" - ) - suspend fun getLocalWithUpdatable(id: String): Map - - @Query( - "SELECT online.*, version.* FROM repo " + - "INNER JOIN online ON online.repo_url = repo.url " + - "INNER JOIN version ON version.id = online.id " + - "WHERE repo.disable = 0 " - ) - fun getOnlineAllAsFlow(): Flow>> - - @Query( - "SELECT * FROM repo " + - "INNER JOIN version ON version.repo_url = repo.url " + - "WHERE repo.disable = 0 AND version.id = :id " - ) - suspend fun getVersionWithRepo(id: String): Map> -} \ 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 36e1fdc0..6015a1b4 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 @@ -1,39 +1,56 @@ package dev.sanmer.mrepo.database.dao import androidx.room.Dao -import androidx.room.Delete import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import dev.sanmer.mrepo.database.entity.LocalModuleEntity +import androidx.room.Transaction +import dev.sanmer.mrepo.database.entity.local.LocalModuleEntity +import dev.sanmer.mrepo.model.local.LocalModule import kotlinx.coroutines.flow.Flow @Dao interface LocalDao { - @Query("SELECT * FROM local") - fun getAllAsFlow(): Flow> - - @Query("SELECT * FROM local") - fun getAll(): List + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertLocal(value: LocalModuleEntity) @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(value: LocalModuleEntity) + suspend fun insertLocal(list: List) @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(list: List) + suspend fun insertUpdatable(value: LocalModuleEntity.Updatable) - @Delete - suspend fun delete(list: List) + @Query("DELETE FROM local_updatable WHERE id NOT IN (:list)") + suspend fun deleteUpdatableNotIn(list: List) - @Query("DELETE FROM local") - suspend fun deleteAll() + @Query("DELETE FROM local WHERE id NOT IN (:list)") + suspend fun deleteLocalNotIn(list: List) - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insertUpdatable(value: LocalModuleEntity.Updatable) + @Transaction + suspend fun updateLocal(list: List) { + val moduleIds = list.map { it.id } - @Query("SELECT * FROM local_updatable WHERE id = :id") - suspend fun getUpdatableOrNull(id: String): LocalModuleEntity.Updatable? + deleteUpdatableNotIn(moduleIds) + deleteLocalNotIn(moduleIds) + insertLocal(list.map { LocalModuleEntity(it) }) + } + + @Query("SELECT * FROM local") + fun getLocalAllAsFlow(): Flow> - @Delete - suspend fun deleteUpdatable(values: List) + @Query( + "SELECT * FROM local " + + "LEFT JOIN local_updatable ON local_updatable.id = local.id " + ) + fun getLocalAndUpdatableAllAsFlow(): Flow> + + @Query( + "SELECT * FROM local " + + "LEFT JOIN local_updatable ON local_updatable.id = local.id " + + "WHERE local.id = :id" + ) + suspend fun getLocalAndUpdatableById(id: String): Map + + @Query("SELECT * FROM local_updatable WHERE id = :id") + suspend fun getUpdatable(id: String): LocalModuleEntity.Updatable? } \ 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 deleted file mode 100644 index 6a202275..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/OnlineDao.kt +++ /dev/null @@ -1,19 +0,0 @@ -package dev.sanmer.mrepo.database.dao - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query -import dev.sanmer.mrepo.database.entity.OnlineModuleEntity - -@Dao -interface OnlineDao { - @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 online WHERE repo_url = :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 779dfb76..411e10ab 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 @@ -1,24 +1,93 @@ package dev.sanmer.mrepo.database.dao import androidx.room.Dao -import androidx.room.Delete import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import dev.sanmer.mrepo.database.entity.RepoEntity +import androidx.room.Transaction +import dev.sanmer.mrepo.database.entity.online.OnlineModuleEntity +import dev.sanmer.mrepo.database.entity.online.RepoEntity +import dev.sanmer.mrepo.database.entity.online.VersionItemEntity +import dev.sanmer.mrepo.model.online.ModulesJson import kotlinx.coroutines.flow.Flow @Dao interface RepoDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertRepo(value: RepoEntity) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertOnline(list: List) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertVersion(list: List) + + @Query("DELETE FROM repo WHERE url = :url") + suspend fun deleteRepoByUrl(url: String) + + @Query("DELETE FROM online WHERE repo_url = :repoUrl") + suspend fun deleteOnlineByUrl(repoUrl: String) + + @Query("DELETE FROM online WHERE repo_url = :repoUrl AND id NOT IN (:list)") + suspend fun deleteOnlineNotIn(repoUrl: String, list: List) + + @Query("DELETE FROM version WHERE repo_url = :repoUrl") + suspend fun deleteVersionByUrl(repoUrl: String) + + @Query("DELETE FROM version WHERE repo_url = :repoUrl AND id NOT IN (:list)") + suspend fun deleteVersionNotIn(repoUrl: String, list: List) + + @Transaction + suspend fun updateRepo(repo: RepoEntity, modulesJson: ModulesJson) { + val moduleIds = modulesJson.modules.map { it.id } + + insertRepo(repo.copy(modulesJson)) + + deleteOnlineNotIn(repo.url, moduleIds) + insertOnline( + modulesJson.modules.map { + OnlineModuleEntity(repo.url, it) + } + ) + + deleteVersionNotIn(repo.url, moduleIds) + insertVersion( + modulesJson.modules.map { module -> + module.versions.map { + VersionItemEntity(repo.url, module.id, it) + } + }.flatten() + ) + } + + @Transaction + suspend fun deleteRepo(url: String) { + deleteRepoByUrl(url) + deleteOnlineByUrl(url) + deleteVersionByUrl(url) + } + @Query("SELECT * FROM repo") - fun getAllAsFlow(): Flow> + fun getRepoAllAsFlow(): Flow> @Query("SELECT * FROM repo") - suspend fun getAll(): List + suspend fun getRepoAll(): List - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(value: RepoEntity) + @Query( + "SELECT online.*, version.* FROM repo " + + "INNER JOIN online ON online.repo_url = repo.url " + + "INNER JOIN version ON version.id = online.id " + + "WHERE repo.disable = 0 " + ) + fun getOnlineAndVersionAllAsFlow(): Flow>> + + @Query("SELECT * FROM online WHERE id = :id") + suspend fun getOnlineById(id: String): List - @Delete - suspend fun delete(value: RepoEntity) + @Query( + "SELECT * FROM repo " + + "INNER JOIN version ON version.repo_url = repo.url " + + "WHERE repo.disable = 0 AND version.id = :id " + ) + suspend fun getVersionAndRepoById(id: String): Map> } \ 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 deleted file mode 100644 index 2d559cfe..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/dao/VersionDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package dev.sanmer.mrepo.database.dao - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query -import dev.sanmer.mrepo.database.entity.VersionItemEntity - -@Dao -interface VersionDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(list: List) - - @Query("DELETE FROM version WHERE repo_url = :repoUrl") - suspend fun deleteByUrl(repoUrl: String) -} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/di/DatabaseModule.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/di/DatabaseModule.kt index c1214d97..fc21030e 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/di/DatabaseModule.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/di/DatabaseModule.kt @@ -1,17 +1,12 @@ package dev.sanmer.mrepo.database.di import android.content.Context -import dev.sanmer.mrepo.database.AppDatabase -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 dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import dev.sanmer.mrepo.database.AppDatabase import javax.inject.Singleton @Module @@ -21,25 +16,13 @@ object DatabaseModule { @Singleton fun providesAppDatabase( @ApplicationContext context: Context - ): AppDatabase = AppDatabase.build(context) - - @Provides - @Singleton - fun providesRepoDao(db: AppDatabase): RepoDao = db.repoDao() - - @Provides - @Singleton - fun providesOnlineDao(db: AppDatabase): OnlineDao = db.onlineDao() - - @Provides - @Singleton - fun providesVersionDao(db: AppDatabase): VersionDao = db.versionDao() + ) = AppDatabase.build(context) @Provides @Singleton - fun providesLocalDao(db: AppDatabase): LocalDao = db.localDao() + fun providesRepoDao(db: AppDatabase) = db.repoDao() @Provides @Singleton - fun providesJoinDao(db: AppDatabase): JoinDao = db.joinDao() + fun providesLocalDao(db: AppDatabase) = db.localDao() } \ 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/LocalModuleEntity.kt similarity index 96% rename from app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Local.kt rename to app/src/main/kotlin/dev/sanmer/mrepo/database/entity/local/LocalModuleEntity.kt index be971f66..c5eeeb8f 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Local.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/local/LocalModuleEntity.kt @@ -1,4 +1,4 @@ -package dev.sanmer.mrepo.database.entity +package dev.sanmer.mrepo.database.entity.local import androidx.room.ColumnInfo import androidx.room.Entity 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/OnlineModuleEntity.kt similarity index 97% rename from app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Online.kt rename to app/src/main/kotlin/dev/sanmer/mrepo/database/entity/online/OnlineModuleEntity.kt index f1affed1..4494a017 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Online.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/online/OnlineModuleEntity.kt @@ -1,4 +1,4 @@ -package dev.sanmer.mrepo.database.entity +package dev.sanmer.mrepo.database.entity.online import androidx.room.ColumnInfo import androidx.room.Embedded diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Repo.kt b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/online/RepoEntity.kt similarity index 89% rename from app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Repo.kt rename to app/src/main/kotlin/dev/sanmer/mrepo/database/entity/online/RepoEntity.kt index cb4da9e8..1c8fe6ae 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Repo.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/online/RepoEntity.kt @@ -1,4 +1,4 @@ -package dev.sanmer.mrepo.database.entity +package dev.sanmer.mrepo.database.entity.online import androidx.room.Embedded import androidx.room.Entity @@ -43,8 +43,4 @@ data class RepoEntity( support = original.support ) } - - companion object { - 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/online/VersionItemEntity.kt similarity index 95% rename from app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Version.kt rename to app/src/main/kotlin/dev/sanmer/mrepo/database/entity/online/VersionItemEntity.kt index 120df5c9..cc97587e 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/Version.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/database/entity/online/VersionItemEntity.kt @@ -1,4 +1,4 @@ -package dev.sanmer.mrepo.database.entity +package dev.sanmer.mrepo.database.entity.online import androidx.room.ColumnInfo import androidx.room.Entity 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 65861aa6..46288c2a 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/repository/LocalRepository.kt @@ -1,16 +1,11 @@ package dev.sanmer.mrepo.repository -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.OnlineModuleEntity -import dev.sanmer.mrepo.database.entity.RepoEntity -import dev.sanmer.mrepo.database.entity.VersionItemEntity +import dev.sanmer.mrepo.database.entity.local.LocalModuleEntity +import dev.sanmer.mrepo.database.entity.online.RepoEntity import dev.sanmer.mrepo.model.local.LocalModule -import dev.sanmer.mrepo.model.online.OnlineModule +import dev.sanmer.mrepo.model.online.ModulesJson import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext @@ -20,125 +15,91 @@ import javax.inject.Singleton @Singleton class LocalRepository @Inject constructor( private val repoDao: RepoDao, - private val onlineDao: OnlineDao, - private val versionDao: VersionDao, - private val localDao: LocalDao, - private val joinDao: JoinDao + private val localDao: LocalDao ) { - fun getLocalAllAsFlow() = localDao.getAllAsFlow().map { data -> - data.map { it.toModule() } - } - - fun getLocalWithUpdatableAllAsFlow() = joinDao.getLocalWithUpdatableAll() - .map { entries -> - entries.map { - val module = it.key.toModule() - val updatable = it.value?.updatable ?: true - module to updatable - } - } - - suspend fun getLocalAll() = withContext(Dispatchers.IO) { - localDao.getAll().map { it.toModule() } + suspend fun insertRepo(value: RepoEntity) = withContext(Dispatchers.IO) { + repoDao.insertRepo(value) } - suspend fun getLocalWithUpdatableOrNull(id: String) = withContext(Dispatchers.IO) { - joinDao.getLocalWithUpdatable(id) - .map { - val module = it.key.toModule() - val updatable = it.value?.updatable ?: true - module to updatable - }.firstOrNull() + suspend fun insertRepo(url: String) = withContext(Dispatchers.IO) { + repoDao.insertRepo(RepoEntity(url)) } - suspend fun insertLocal(value: LocalModule) = withContext(Dispatchers.IO) { - localDao.insert(LocalModuleEntity(value)) + suspend fun deleteRepo(value: RepoEntity) = withContext(Dispatchers.IO) { + repoDao.deleteRepo(value.url) } - suspend fun insertLocal(list: List) = withContext(Dispatchers.IO) { - localDao.insert(list.map { LocalModuleEntity(it) }) + suspend fun updateRepo(repo: RepoEntity, modulesJson: ModulesJson) = withContext(Dispatchers.IO) { + repoDao.updateRepo(repo, modulesJson) } - suspend fun deleteLocal(list: List) = withContext(Dispatchers.IO) { - localDao.delete(list.map { LocalModuleEntity(it) }) - } + fun getRepoAllAsFlow() = repoDao.getRepoAllAsFlow() - suspend fun deleteLocalAll() = withContext(Dispatchers.IO) { - localDao.deleteAll() + suspend fun getRepoAll() = withContext(Dispatchers.IO) { + repoDao.getRepoAll() } - suspend fun insertLocalUpdatable(id: String, updatable: Boolean) = withContext(Dispatchers.IO) { - localDao.insertUpdatable( - LocalModuleEntity.Updatable(id = id, updatable = updatable) - ) + fun getOnlineAllAsFlow() = repoDao.getOnlineAndVersionAllAsFlow().map { entries -> + entries.map { (module, versions) -> + module.toJson( + versions = versions.map { it.toJson() } + ) + } } - suspend fun isLocalUpdatable(id: String) = withContext(Dispatchers.IO) { - localDao.getUpdatableOrNull(id)?.updatable ?: true + suspend fun getOnlineById(id: String) = withContext(Dispatchers.IO) { + repoDao.getOnlineById(id).map { it.toJson() } } - suspend fun deleteLocalUpdatable(removed: List) = withContext(Dispatchers.IO) { - localDao.deleteUpdatable( - removed.map { - LocalModuleEntity.Updatable(id = it.id, updatable = false) - } - ) + suspend fun getVersionAndRepoById(id: String) = withContext(Dispatchers.IO) { + repoDao.getVersionAndRepoById(id).mapValues { entry -> + entry.value.map { it.toJson() } + } } - fun getRepoAllAsFlow() = repoDao.getAllAsFlow() - - suspend fun getRepoAll() = withContext(Dispatchers.IO) { - repoDao.getAll() + suspend fun getVersionById(id: String) = withContext(Dispatchers.IO) { + repoDao.getVersionAndRepoById(id).flatMap { entry -> + entry.value.map { it.toJson() } + } } - suspend fun insertRepo(value: RepoEntity) = withContext(Dispatchers.IO) { - repoDao.insert(value) + suspend fun insertLocal(value: LocalModule) = withContext(Dispatchers.IO) { + localDao.insertLocal(LocalModuleEntity(value)) } - suspend fun deleteRepo(value: RepoEntity) = withContext(Dispatchers.IO) { - repoDao.delete(value) + suspend fun updateLocal(list: List) = withContext(Dispatchers.IO) { + localDao.updateLocal(list) } - fun getOnlineAllAsFlow() = joinDao.getOnlineAllAsFlow().map { entries -> - entries.map { (module, versions) -> - module.toJson( - versions = versions.map { it.toJson() } - ) - } + suspend fun insertUpdatable(id: String, updatable: Boolean) = withContext(Dispatchers.IO) { + localDao.insertUpdatable( + LocalModuleEntity.Updatable(id = id, updatable = updatable) + ) } - suspend fun getOnlineAllById(id: String) = withContext(Dispatchers.IO) { - onlineDao.getAllById(id).map { it.toJson() } + fun getLocalAllAsFlow() = localDao.getLocalAllAsFlow().map { data -> + data.map { it.toModule() } } - suspend fun insertOnline(repoUrl: String, list: List) = withContext(Dispatchers.IO) { - val modules = list.map { - OnlineModuleEntity(repoUrl = repoUrl, original = it) - } - val versions = list.map { module -> - module.versions.map { - VersionItemEntity(repoUrl = repoUrl, id = module.id, original = it) + fun getLocalAndUpdatableAllAsFlow() = localDao.getLocalAndUpdatableAllAsFlow() + .map { entries -> + entries.map { + val module = it.key.toModule() + val updatable = it.value?.updatable ?: true + module to updatable } - }.flatten() - - versionDao.insert(versions) - onlineDao.insert(modules) - } - - suspend fun deleteOnlineByUrl(repoUrl: String) = withContext(Dispatchers.IO) { - versionDao.deleteByUrl(repoUrl) - onlineDao.deleteByUrl(repoUrl) - } - - suspend fun getVersionById(id: String) = withContext(Dispatchers.IO) { - joinDao.getVersionWithRepo(id).values.flatMap { versions -> - versions.map { it.toJson() } } + + suspend fun getLocalAndUpdatableById(id: String) = withContext(Dispatchers.IO) { + localDao.getLocalAndUpdatableById(id) + .map { + val module = it.key.toModule() + val updatable = it.value?.updatable ?: true + module to updatable + }.firstOrNull() } - suspend fun getVersionByIdWithRepo(id: String) = withContext(Dispatchers.IO) { - joinDao.getVersionWithRepo(id).mapValues { entry -> - entry.value.map { it.toJson() } - } + suspend fun isUpdatable(id: String) = withContext(Dispatchers.IO) { + localDao.getUpdatable(id)?.updatable ?: true } } \ No newline at end of file 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 c4b26262..eb7caa87 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/repository/ModulesRepository.kt @@ -2,7 +2,7 @@ package dev.sanmer.mrepo.repository import dev.sanmer.mrepo.Compat import dev.sanmer.mrepo.compat.NetworkCompat.runRequest -import dev.sanmer.mrepo.database.entity.RepoEntity +import dev.sanmer.mrepo.database.entity.online.RepoEntity import dev.sanmer.mrepo.stub.IRepoManager import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -20,13 +20,7 @@ class ModulesRepository @Inject constructor( runCatching { mm.modules.toList() }.onSuccess { modules -> - val moduleIds = modules.map { it.id } - val locals = localRepository.getLocalAll() - val removed = locals.filter { !moduleIds.contains(it.id) } - - localRepository.deleteLocal(removed) - localRepository.deleteLocalUpdatable(removed) - localRepository.insertLocal(modules) + localRepository.updateLocal(modules) }.onFailure { Timber.e(it, "getLocalAll") } @@ -53,11 +47,11 @@ class ModulesRepository @Inject constructor( runRequest { val api = IRepoManager.build(repo.url) api.modules.execute() - }.onSuccess { modulesJson -> - localRepository.insertRepo(repo.copy(modulesJson)) - localRepository.deleteOnlineByUrl(repo.url) - localRepository.insertOnline(repoUrl = repo.url, list = modulesJson.modules) + }.onSuccess { + localRepository.updateRepo(repo, it) }.onFailure { Timber.e(it, "getRepo: ${repo.url}") } + + suspend fun getRepo(repoUrl: String) = getRepo(RepoEntity(repoUrl)) } \ No newline at end of file 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 84768e76..ea81188c 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,6 @@ 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.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 @@ -58,7 +57,7 @@ class MainActivity : ComponentActivity() { LaunchedEffect(userPreferences) { if (preferences.workingMode.isSetup) { Timber.d("add demo repository") - localRepository.insertRepo(Const.DEMO_REPO_URL.toRepo()) + localRepository.insertRepo(Const.DEMO_REPO_URL) } Compat.init(preferences.workingMode) 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 1adeaef6..0a04d9f7 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 @@ -28,7 +28,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.database.entity.RepoEntity +import dev.sanmer.mrepo.database.entity.online.RepoEntity import dev.sanmer.mrepo.model.online.VersionItem import dev.sanmer.mrepo.ui.component.LabelItem import dev.sanmer.mrepo.ui.component.VersionItemBottomSheet 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 f468b58d..acce75be 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 @@ -19,7 +19,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.database.entity.RepoEntity +import dev.sanmer.mrepo.database.entity.online.RepoEntity @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 13baa865..fae04fb1 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 @@ -39,7 +39,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.database.entity.RepoEntity +import dev.sanmer.mrepo.database.entity.online.RepoEntity import dev.sanmer.mrepo.ui.component.LabelItem import dev.sanmer.mrepo.ui.utils.expandedShape import dev.sanmer.mrepo.utils.extensions.shareText diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/InstallViewModel.kt b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/InstallViewModel.kt index d5db7ba5..cedf8172 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/InstallViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/InstallViewModel.kt @@ -100,9 +100,9 @@ class InstallViewModel @Inject constructor( } private suspend fun install(zipPath: String) = withContext(Dispatchers.IO) { + val userPreferences = userPreferencesRepository.data.first() + val deleteZipFile = userPreferences.deleteZipFile val zipFile = File(zipPath) - val deleteZipFile = userPreferencesRepository - .data.first().deleteZipFile val callback = object : IInstallCallback.Stub() { override fun onStdout(msg: String) { 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 d86846b8..cd643a28 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModuleViewModel.kt @@ -11,8 +11,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import dev.sanmer.mrepo.Compat -import dev.sanmer.mrepo.database.entity.RepoEntity -import dev.sanmer.mrepo.database.entity.RepoEntity.Companion.toRepo +import dev.sanmer.mrepo.database.entity.online.RepoEntity import dev.sanmer.mrepo.model.json.UpdateJson import dev.sanmer.mrepo.model.local.LocalModule import dev.sanmer.mrepo.model.online.OnlineModule @@ -69,24 +68,22 @@ class ModuleViewModel @Inject constructor( } private fun loadData() = viewModelScope.launch { - localRepository.getOnlineAllById(moduleId).first().let { - online = it - } + online = localRepository.getOnlineById(moduleId).maxBy { it.versionCode } - localRepository.getLocalWithUpdatableOrNull(moduleId)?.let { (module, update) -> + localRepository.getLocalAndUpdatableById(moduleId)?.let { (module, update) -> local = module notifyUpdates = update } versions.addAll( - localRepository.getVersionByIdWithRepo(moduleId).flatMap { entry -> + localRepository.getVersionAndRepoById(moduleId).flatMap { entry -> entry.value.map { entry.key to it } }.sortedByDescending { it.second.versionCode } ) if (installed) { UpdateJson.load(local!!.updateJson)?.let { - versions.add(0, "Update Json".toRepo() to it) + versions.add(0, RepoEntity("Update Json") to it) } } } @@ -94,7 +91,7 @@ class ModuleViewModel @Inject constructor( fun setUpdatesTag(updatable: Boolean) { viewModelScope.launch { notifyUpdates = updatable - localRepository.insertLocalUpdatable(moduleId, updatable) + localRepository.insertUpdatable(moduleId, updatable) } } diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt index bc41808e..b3201a66 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/ModulesViewModel.kt @@ -215,7 +215,7 @@ class ModulesViewModel @Inject constructor( fun getVersionItem(module: LocalModule): VersionItem? { viewModelScope.launch { - if (!localRepository.isLocalUpdatable(module.id)) { + if (!localRepository.isUpdatable(module.id)) { versionItems.remove(module.id) return@launch } 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 076913f3..8330addc 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoriesViewModel.kt @@ -6,8 +6,7 @@ import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import dev.sanmer.mrepo.database.entity.RepoEntity -import dev.sanmer.mrepo.database.entity.RepoEntity.Companion.toRepo +import dev.sanmer.mrepo.database.entity.online.RepoEntity import dev.sanmer.mrepo.repository.LocalRepository import dev.sanmer.mrepo.repository.ModulesRepository import kotlinx.coroutines.flow.MutableStateFlow @@ -57,7 +56,7 @@ class RepositoriesViewModel @Inject constructor( ) { viewModelScope.launch { refreshing { - modulesRepository.getRepo(url.toRepo()) + modulesRepository.getRepo(url) .onFailure { Timber.e(it, "insert: $url") onFailure(it) @@ -75,7 +74,6 @@ class RepositoriesViewModel @Inject constructor( fun delete(repo: RepoEntity) { viewModelScope.launch { localRepository.deleteRepo(repo) - localRepository.deleteOnlineByUrl(repo.url) } } 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 306615ac..dc89de51 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/viewmodel/RepositoryViewModel.kt @@ -59,7 +59,7 @@ class RepositoryViewModel @Inject constructor( private fun dataObserver() { combine( localRepository.getOnlineAllAsFlow(), - localRepository.getLocalWithUpdatableAllAsFlow(), + localRepository.getLocalAndUpdatableAllAsFlow(), repositoryMenu ) { online, local, menu -> cacheFlow.value = online.map { From 739c33e78faf5fb9e43972003454805043f68fb7 Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 22:12:54 +0800 Subject: [PATCH 4/8] Remove `scaleIn` from enterTransition --- .../dev/sanmer/mrepo/ui/navigation/graphs/Repository.kt | 3 +-- .../dev/sanmer/mrepo/ui/navigation/graphs/Settings.kt | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Repository.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Repository.kt index 354965b2..7db01943 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Repository.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Repository.kt @@ -2,7 +2,6 @@ package dev.sanmer.mrepo.ui.navigation.graphs import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavType @@ -37,7 +36,7 @@ fun NavGraphBuilder.repositoryScreen( composable( route = RepositoryScreen.View.route, arguments = listOf(navArgument("moduleId") { type = NavType.StringType }), - enterTransition = { scaleIn() + fadeIn() }, + enterTransition = { fadeIn() }, exitTransition = { fadeOut() } ) { ViewScreen( diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Settings.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Settings.kt index fd31f41c..1321b0fb 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Settings.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/navigation/graphs/Settings.kt @@ -2,7 +2,6 @@ package dev.sanmer.mrepo.ui.navigation.graphs import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable @@ -40,7 +39,7 @@ fun NavGraphBuilder.settingsScreen( composable( route = SettingsScreen.Repositories.route, - enterTransition = { scaleIn() + fadeIn() }, + enterTransition = { fadeIn() }, exitTransition = { fadeOut() } ) { RepositoriesScreen( @@ -50,7 +49,7 @@ fun NavGraphBuilder.settingsScreen( composable( route = SettingsScreen.App.route, - enterTransition = { scaleIn() + fadeIn() }, + enterTransition = { fadeIn() }, exitTransition = { fadeOut() } ) { AppScreen( @@ -60,7 +59,7 @@ fun NavGraphBuilder.settingsScreen( composable( route = SettingsScreen.WorkingMode.route, - enterTransition = { scaleIn() + fadeIn() }, + enterTransition = { fadeIn() }, exitTransition = { fadeOut() } ) { WorkingModeScreen( @@ -70,7 +69,7 @@ fun NavGraphBuilder.settingsScreen( composable( route = SettingsScreen.About.route, - enterTransition = { scaleIn() + fadeIn() }, + enterTransition = { fadeIn() }, exitTransition = { fadeOut() } ) { AboutScreen( From 44db723b3957d37851dc116acc9796dd19c0c5f4 Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 22:29:54 +0800 Subject: [PATCH 5/8] Optimize `RepositoriesScreen` --- .../ui/screens/repository/RepositoryMenu.kt | 2 +- .../repository/view/pages/AboutPage.kt | 2 +- .../settings/repositories/RepositoriesList.kt | 18 +- .../repositories/RepositoriesScreen.kt | 2 +- .../settings/repositories/RepositoryItem.kt | 174 ++++++++---------- 5 files changed, 86 insertions(+), 112 deletions(-) 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 7d9beafc..2d1e8bcd 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 @@ -40,7 +40,7 @@ import dev.sanmer.mrepo.ui.providable.LocalUserPreferences import dev.sanmer.mrepo.ui.utils.expandedShape import dev.sanmer.mrepo.viewmodel.RepositoryViewModel.OnlineState -val options = listOf( +private val options = listOf( Option.Name to R.string.menu_sort_option_name, Option.UpdatedTime to R.string.menu_sort_option_updated ) diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt index e940f778..3c193a3b 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt @@ -39,7 +39,7 @@ fun AboutPage( ValueItem( key = stringResource(id = R.string.view_module_homepage), value = online.metadata.homepage, - icon = R.drawable.world_www + icon = R.drawable.home ) ValueItem( 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 acce75be..f83159e8 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 @@ -40,7 +40,7 @@ fun RepositoriesList( ) { repo -> RepositoryItem( repo = repo, - toggle = { insert(it) }, + onToggle = { insert(it) }, onUpdate = update, onDelete = delete, ) @@ -50,7 +50,7 @@ fun RepositoriesList( @Composable private fun RepositoryItem( repo: RepoEntity, - toggle: (RepoEntity) -> Unit, + onToggle: (RepoEntity) -> Unit, onUpdate: (RepoEntity) -> Unit, onDelete: (RepoEntity) -> Unit, ) { @@ -63,9 +63,9 @@ private fun RepositoryItem( RepositoryItem( repo = repo, - toggle = { toggle(repo.copy(disable = it)) }, - update = { onUpdate(repo) }, - delete = { delete = true } + toggle = { onToggle(repo.copy(disable = it)) }, + onUpdate = { onUpdate(repo) }, + onDelete = { delete = true } ) } @@ -77,10 +77,8 @@ private fun DeleteDialog( ) = AlertDialog( shape = RoundedCornerShape(20.dp), onDismissRequest = onClose, - title = { Text(text = stringResource(id = R.string.dialog_attention)) }, - text = { - Text(text = stringResource(id = R.string.repo_delete_dialog_desc, repo.name)) - }, + title = { Text(text = repo.name) }, + text = { Text(text = stringResource(id = R.string.repo_delete_dialog_desc)) }, confirmButton = { TextButton( onClick = { @@ -88,7 +86,7 @@ private fun DeleteDialog( onClose() } ) { - Text(text = stringResource(id = R.string.repo_options_delete)) + Text(text = stringResource(id = R.string.dialog_ok)) } }, dismissButton = { diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt index b0f78a71..4a994d3b 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt @@ -175,7 +175,7 @@ private fun AddDialog( onClick = onDone, enabled = domain.isNotBlank() ) { - Text(text = stringResource(id = R.string.repo_add_dialog_add)) + Text(text = stringResource(id = R.string.dialog_ok)) } }, dismissButton = { 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 fae04fb1..bdb1a03b 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 @@ -2,28 +2,23 @@ package dev.sanmer.mrepo.ui.screens.settings.repositories import androidx.annotation.DrawableRes import androidx.annotation.StringRes +import androidx.compose.animation.animateContentSize import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -41,7 +36,7 @@ import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R import dev.sanmer.mrepo.database.entity.online.RepoEntity import dev.sanmer.mrepo.ui.component.LabelItem -import dev.sanmer.mrepo.ui.utils.expandedShape +import dev.sanmer.mrepo.utils.extensions.openUrl import dev.sanmer.mrepo.utils.extensions.shareText import dev.sanmer.mrepo.utils.extensions.toDateTime @@ -49,8 +44,8 @@ import dev.sanmer.mrepo.utils.extensions.toDateTime fun RepositoryItem( repo: RepoEntity, toggle: (Boolean) -> Unit, - update: () -> Unit, - delete: () -> Unit, + onUpdate: () -> Unit, + onDelete: () -> Unit, ) = Surface( shape = RoundedCornerShape(15.dp), color = MaterialTheme.colorScheme.surface, @@ -61,6 +56,8 @@ fun RepositoryItem( modifier = Modifier .padding(all = 15.dp) .fillMaxWidth() + .animateContentSize(), + verticalArrangement = Arrangement.spacedBy(12.dp) ) { Row( verticalAlignment = Alignment.Top @@ -104,111 +101,90 @@ fun RepositoryItem( ) } - Row( - modifier = Modifier.padding(top = 12.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Spacer(modifier = Modifier.weight(1f)) - - var open by remember { mutableStateOf(false) } - if (open) { - BottomSheet( - repo = repo, - onDelete = delete, - onClose = { open = false } - ) - } - - ButtonItem( - icon = R.drawable.at, - onClick = { open = true } - ) + var expand by remember { mutableStateOf(false) } + OpsButtonItem( + expand = expand, + onExpandChanged = { expand = it }, + onDelete = onDelete, + onUpdate = onUpdate + ) - ButtonItem( - icon = R.drawable.cloud_download, - label = R.string.repo_options_update, - onClick = update - ) + if (expand) { + InfoButtonItem(repo = repo) } } } @Composable -private fun BottomSheet( - repo: RepoEntity, +private fun OpsButtonItem( + expand: Boolean, + onExpandChanged: (Boolean) -> Unit, onDelete: () -> Unit, - onClose: () -> Unit -) = ModalBottomSheet( - onDismissRequest = onClose, - sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), - shape = BottomSheetDefaults.expandedShape(15.dp), - windowInsets = WindowInsets.navigationBars + onUpdate: () -> Unit +) = Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically ) { - val context = LocalContext.current - - Column( - modifier = Modifier - .padding(bottom = 18.dp) - .padding(horizontal = 18.dp), - verticalArrangement = Arrangement.spacedBy(18.dp) - ) { - Row( - verticalAlignment = Alignment.Top - ) { - Column( - modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(2.dp) - ) { - Text( - text = repo.name, - style = MaterialTheme.typography.titleSmall - .copy(fontWeight = FontWeight.Bold), - maxLines = 2, - overflow = TextOverflow.Ellipsis - ) + Spacer(modifier = Modifier.weight(1f)) + + ButtonItem( + icon = if (expand) { + R.drawable.arrow_badge_up + } else { + R.drawable.arrow_badge_down + }, + onClick = { onExpandChanged(!expand) } + ) + + ButtonItem( + icon = R.drawable.cloud_download, + label = R.string.repo_options_update, + onClick = onUpdate + ) + + ButtonItem( + icon = R.drawable.trash, + label = R.string.repo_options_delete, + onClick = onDelete + ) +} - Text( - text = stringResource(id = R.string.module_update_at, repo.timestamp.toDateTime()), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.outline - ) - } +@Composable +private fun InfoButtonItem( + repo: RepoEntity +) = Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically +) { + val context = LocalContext.current - LabelItem( - text = stringResource(id = R.string.repo_modules, repo.size), - upperCase = false - ) - } + Spacer(modifier = Modifier.weight(1f)) - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - textStyle = MaterialTheme.typography.bodyMedium, - shape = RoundedCornerShape(15.dp), - value = repo.url, - onValueChange = {}, - readOnly = true, - singleLine = true + if (repo.metadata.donate.isNotBlank()) { + ButtonItem( + icon = R.drawable.currency_dollar, + onClick = { context.openUrl(repo.metadata.donate) } ) + } - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Spacer(modifier = Modifier.weight(1f)) - - ButtonItem( - icon = R.drawable.share, - onClick = { context.shareText(repo.url) } - ) + if (repo.metadata.support.isNotBlank()) { + ButtonItem( + icon = R.drawable.heart_handshake, + onClick = { context.openUrl(repo.metadata.support) } + ) + } - ButtonItem( - icon = R.drawable.trash, - label = R.string.repo_options_delete, - onClick = onDelete - ) - } + if (repo.metadata.homepage.isNotBlank()) { + ButtonItem( + icon = R.drawable.home, + onClick = { context.openUrl(repo.metadata.homepage) } + ) } + + ButtonItem( + icon = R.drawable.share, + onClick = { context.shareText(repo.url) } + ) } @Composable From 8a741ca7c7eb7fa098589c30ef86d35ace01369e Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 22:39:30 +0800 Subject: [PATCH 6/8] Optimize `AboutScreen` --- .../ui/screens/settings/about/AboutScreen.kt | 138 ++++++++++-------- 1 file changed, 75 insertions(+), 63 deletions(-) diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/about/AboutScreen.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/about/AboutScreen.kt index 8bf65b37..9c5f4f8b 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/about/AboutScreen.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/about/AboutScreen.kt @@ -1,5 +1,6 @@ package dev.sanmer.mrepo.ui.screens.settings.about +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -17,7 +18,6 @@ import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults @@ -60,10 +60,11 @@ fun AboutScreen( modifier = Modifier .padding(innerPadding) .fillMaxWidth() - .verticalScroll(rememberScrollState()), - horizontalAlignment = Alignment.CenterHorizontally + .verticalScroll(rememberScrollState()) + .padding(all = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(20.dp) ) { - Spacer(modifier = Modifier.height(20.dp)) Logo( icon = R.drawable.launcher_outline, modifier = Modifier.size(65.dp), @@ -72,82 +73,93 @@ fun AboutScreen( fraction = 0.7f ) - Spacer(modifier = Modifier.height(20.dp)) - Text( - text = stringResource(id = R.string.app_name), - style = MaterialTheme.typography.titleLarge - ) - Text( - text = stringResource(id = R.string.about_app_version, - BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.padding(top = 5.dp) - ) - - Spacer(modifier = Modifier.height(20.dp)) - FilledTonalButton( - onClick = { context.openUrl(Const.GITHUB_URL) } + Column( + horizontalAlignment = Alignment.CenterHorizontally ) { - Icon( - painter = painterResource(id = R.drawable.github), - contentDescription = null + Text( + text = stringResource(id = R.string.app_name), + style = MaterialTheme.typography.titleLarge + ) + + Text( + text = stringResource( + id = R.string.about_app_version, + BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE + ), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(top = 5.dp) ) - Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing)) - Text(text = stringResource(id = R.string.about_github)) } - Row( - modifier = Modifier.padding(top = 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(8.dp) ) { FilledTonalButton( - onClick = { context.openUrl(Const.TRANSLATE_URL) } + onClick = { context.openUrl(Const.GITHUB_URL) } ) { Icon( - painter = painterResource(id = R.drawable.weblate), - contentDescription = null, - modifier = Modifier.size(ButtonDefaults.IconSize) + painter = painterResource(id = R.drawable.github), + contentDescription = null ) Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing)) - Text(text = stringResource(id = R.string.about_weblate)) + Text(text = stringResource(id = R.string.about_github)) } - FilledTonalButton( - onClick = { context.openUrl(Const.TELEGRAM_URL) } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - Icon( - painter = painterResource(id = R.drawable.telegram), - contentDescription = null - ) - Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing)) - Text(text = stringResource(id = R.string.about_telegram)) + FilledTonalButton( + onClick = { context.openUrl(Const.TRANSLATE_URL) } + ) { + Icon( + painter = painterResource(id = R.drawable.weblate), + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize) + ) + Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing)) + Text(text = stringResource(id = R.string.about_weblate)) + } + + FilledTonalButton( + onClick = { context.openUrl(Const.TELEGRAM_URL) } + ) { + Icon( + painter = painterResource(id = R.drawable.telegram), + contentDescription = null + ) + Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing)) + Text(text = stringResource(id = R.string.about_telegram)) + } } } - OutlinedCard( - modifier = Modifier.padding(vertical = 30.dp, horizontal = 20.dp), - shape = RoundedCornerShape(15.dp) - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(all = 15.dp) - ) { - Text( - text = stringResource(id = R.string.about_desc1), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant + Column( + modifier = Modifier + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outline, + shape = RoundedCornerShape(15.dp) ) - Spacer(modifier = Modifier.height(15.dp)) - HtmlText( - text = stringResource(id = R.string.about_desc2, - "Sanmer"), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } + .fillMaxWidth() + .padding(all = 15.dp) + ) { + Text( + text = stringResource(id = R.string.about_desc1), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + Spacer(modifier = Modifier.height(15.dp)) + + HtmlText( + text = stringResource(id = R.string.about_desc2, + "Sanmer"), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) } } } From 7903e374e56797b850efb9cc06dfb380058cbb39 Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 22:39:43 +0800 Subject: [PATCH 7/8] Optimize `WorkingModeScreen` --- .../ui/screens/settings/workingmode/WorkingModeScreen.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeScreen.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeScreen.kt index bb927b87..73070bee 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeScreen.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeScreen.kt @@ -2,10 +2,8 @@ package dev.sanmer.mrepo.ui.screens.settings.workingmode import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -48,12 +46,11 @@ fun WorkingModeScreen( modifier = Modifier .padding(innerPadding) .fillMaxSize() - .verticalScroll(rememberScrollState()), + .verticalScroll(rememberScrollState()) + .padding(vertical = 20.dp), verticalArrangement = Arrangement.spacedBy(20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - Spacer(modifier = Modifier.height(20.dp)) - WorkingModeItem( title = stringResource(id = R.string.setup_root_title), desc = stringResource(id = R.string.setup_root_desc), From 9844c592861b5f10a40283a89d7b984426a778cb Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Thu, 20 Jun 2024 23:39:25 +0800 Subject: [PATCH 8/8] Tidy up code & Remove unused res --- .../mrepo/ui/screens/modules/ModuleItem.kt | 2 +- .../mrepo/ui/screens/modules/ModulesList.kt | 2 +- .../mrepo/ui/screens/modules/ModulesMenu.kt | 2 +- .../mrepo/ui/screens/repository/ModuleItem.kt | 42 ++++++------ .../ui/screens/repository/ModulesList.kt | 2 +- .../ui/screens/repository/RepositoryMenu.kt | 2 +- .../ui/screens/repository/view/ViewTab.kt | 29 +++++---- .../ui/screens/repository/view/ViewTopBar.kt | 15 +++-- .../repository/view/items/LicenseItem.kt | 13 ++-- .../screens/repository/view/items/TagItem.kt | 2 +- .../repository/view/pages/AboutPage.kt | 2 +- .../repository/view/pages/OverviewPage.kt | 3 +- .../repository/view/pages/VersionsPage.kt | 2 +- .../settings/app/items/AppThemeItem.kt | 19 +++--- .../settings/app/items/DarkModeItem.kt | 18 +++--- .../settings/app/items/DownloadPathItem.kt | 6 +- .../settings/app/items/ThemePaletteItem.kt | 64 ++++++++++--------- .../ui/screens/settings/items/NonRootItem.kt | 2 +- .../ui/screens/settings/items/RootItem.kt | 5 +- .../settings/repositories/RepositoriesList.kt | 2 +- .../repositories/RepositoriesScreen.kt | 1 - .../settings/repositories/RepositoryItem.kt | 2 +- .../settings/workingmode/WorkingModeItem.kt | 2 +- .../dev/sanmer/mrepo/ui/theme/Colors.kt | 26 ++++---- .../main/res/drawable/arrow_badge_down.xml | 12 ++++ app/src/main/res/drawable/arrow_badge_up.xml | 12 ++++ app/src/main/res/drawable/home.xml | 24 +++++++ app/src/main/res/drawable/world_www.xml | 60 ----------------- app/src/main/res/values-ar/strings.xml | 5 -- app/src/main/res/values-de/strings.xml | 5 -- app/src/main/res/values-es/strings.xml | 5 -- app/src/main/res/values-fr/strings.xml | 3 - app/src/main/res/values-hi/strings.xml | 5 -- app/src/main/res/values-in/strings.xml | 5 -- app/src/main/res/values-it/strings.xml | 5 -- app/src/main/res/values-ja/strings.xml | 4 -- app/src/main/res/values-pl/strings.xml | 5 -- app/src/main/res/values-pt/strings.xml | 2 - app/src/main/res/values-ro/strings.xml | 5 -- app/src/main/res/values-ru/strings.xml | 5 -- app/src/main/res/values-tr/strings.xml | 5 -- app/src/main/res/values-vi/strings.xml | 5 -- app/src/main/res/values-zh-rCN/strings.xml | 7 +- app/src/main/res/values-zh-rTW/strings.xml | 5 -- app/src/main/res/values/strings.xml | 9 +-- 45 files changed, 190 insertions(+), 268 deletions(-) create mode 100644 app/src/main/res/drawable/arrow_badge_down.xml create mode 100644 app/src/main/res/drawable/arrow_badge_up.xml create mode 100644 app/src/main/res/drawable/home.xml delete mode 100644 app/src/main/res/drawable/world_www.xml 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 9f79afa5..ecdddb07 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 @@ -42,7 +42,7 @@ import dev.sanmer.mrepo.ui.providable.LocalUserPreferences import dev.sanmer.mrepo.utils.extensions.toDate @Composable -fun ModuleItem( +internal fun ModuleItem( module: LocalModule, progress: Float, indeterminate: Boolean = false, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesList.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesList.kt index 471205a2..4b421b82 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesList.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesList.kt @@ -39,7 +39,7 @@ import dev.sanmer.mrepo.viewmodel.ModulesViewModel import kotlinx.coroutines.flow.Flow @Composable -fun ModulesList( +internal fun ModulesList( list: List, state: LazyListState, isProviderAlive: Boolean, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesMenu.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesMenu.kt index d3862436..b78979e8 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesMenu.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/modules/ModulesMenu.kt @@ -41,7 +41,7 @@ private val options = listOf( ) @Composable -fun ModulesMenu( +internal fun ModulesMenu( setMenu: (ModulesMenuCompat) -> Unit ) { val userPreferences = LocalUserPreferences.current 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 86c45ffa..a1d6b73f 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 @@ -29,7 +29,7 @@ import dev.sanmer.mrepo.utils.extensions.toDate import dev.sanmer.mrepo.viewmodel.RepositoryViewModel.OnlineState @Composable -fun ModuleItem( +internal fun ModuleItem( module: OnlineModule, state: OnlineState, modifier: Modifier = Modifier, @@ -43,8 +43,6 @@ fun ModuleItem( ) { val userPreferences = LocalUserPreferences.current val menu = userPreferences.repositoryMenu - val hasLabel = (state.hasLicense && menu.showLicense) - || state.installed Row( modifier = Modifier.padding(all = 10.dp), @@ -73,12 +71,14 @@ fun ModuleItem( ) Spacer(modifier = Modifier.height(2.dp)) + Text( text = module.author, style = MaterialTheme.typography.bodyMedium.copy(), maxLines = 2, overflow = TextOverflow.Ellipsis ) + Text( text = module.versionDisplay, style = MaterialTheme.typography.bodySmall, @@ -94,26 +94,24 @@ fun ModuleItem( ) } - if (hasLabel) { - Row( - modifier = Modifier.padding(top = 4.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(2.dp) - ) { - if (menu.showLicense) { - LabelItem(text = module.metadata.license) - } + Row( + modifier = Modifier.padding(top = 4.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(2.dp) + ) { + if (menu.showLicense) { + LabelItem(text = module.metadata.license) + } - when { - state.updatable -> LabelItem( - text = stringResource(id = R.string.module_new), - containerColor = MaterialTheme.colorScheme.error, - contentColor = MaterialTheme.colorScheme.onError - ) - state.installed -> LabelItem( - text = stringResource(id = R.string.module_installed) - ) - } + when { + state.updatable -> LabelItem( + text = stringResource(id = R.string.module_new), + containerColor = MaterialTheme.colorScheme.error, + contentColor = MaterialTheme.colorScheme.onError + ) + state.installed -> LabelItem( + text = stringResource(id = R.string.module_installed) + ) } } } 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 6250f196..2ece9a61 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 @@ -18,7 +18,7 @@ import dev.sanmer.mrepo.viewmodel.ModuleViewModel import dev.sanmer.mrepo.viewmodel.RepositoryViewModel.OnlineState @Composable -fun ModulesList( +internal fun ModulesList( list: List>, state: LazyListState, navController: NavController 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 2d1e8bcd..990d5a78 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 @@ -46,7 +46,7 @@ private val options = listOf( ) @Composable -fun RepositoryMenu( +internal fun RepositoryMenu( setMenu: (RepositoryMenuCompat) -> Unit ) { val userPreferences = LocalUserPreferences.current diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTab.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTab.kt index 54be379f..86a379d7 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTab.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/ViewTab.kt @@ -19,7 +19,9 @@ import androidx.compose.material3.TabPosition import androidx.compose.material3.TabRow 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.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -35,7 +37,7 @@ import dev.sanmer.mrepo.ui.component.Tab import kotlinx.coroutines.launch @Composable -fun ViewTab( +internal fun ViewTab( state: PagerState, updatableSize: Int, hasAbout: Boolean, @@ -43,17 +45,20 @@ fun ViewTab( ) { val scope = rememberCoroutineScope() - val pages = if (hasAbout) { - listOf( - R.string.view_module_page_overview, - R.string.view_module_page_versions, - R.string.view_module_page_about - ) - } else { - listOf( - R.string.view_module_page_overview, - R.string.view_module_page_versions - ) + val pages by remember(hasAbout) { + derivedStateOf { + when { + hasAbout -> listOf( + R.string.view_module_page_overview, + R.string.view_module_page_versions, + R.string.view_module_page_about + ) + else -> listOf( + R.string.view_module_page_overview, + R.string.view_module_page_versions + ) + } + } } TabRow( 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 643eabe3..a072d45a 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 @@ -14,6 +14,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarScrollBehavior 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.platform.LocalContext @@ -33,7 +36,7 @@ import dev.sanmer.mrepo.ui.screens.repository.view.items.TagItem import dev.sanmer.mrepo.utils.extensions.openUrl @Composable -fun ViewTopBar( +internal fun ViewTopBar( online: OnlineModule, scrollBehavior: TopAppBarScrollBehavior, navController: NavController @@ -71,12 +74,16 @@ fun ViewTopBar( private fun TopBarContent( module: OnlineModule ) { + val context = LocalContext.current val userPreferences = LocalUserPreferences.current val repositoryMenu = userPreferences.repositoryMenu - val context = LocalContext.current - val hasLicense = module.metadata.license.isNotBlank() - val hasDonate = module.metadata.donate.isNotBlank() + val hasLicense by remember { + derivedStateOf { module.metadata.license.isNotBlank() } + } + val hasDonate by remember { + derivedStateOf { module.metadata.donate.isNotBlank() } + } Row( modifier = Modifier.padding(horizontal = 16.dp), diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/LicenseItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/LicenseItem.kt index 1795907e..dbe1ed6b 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/LicenseItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/LicenseItem.kt @@ -22,16 +22,10 @@ import dev.sanmer.mrepo.ui.component.LicenseContent import dev.sanmer.mrepo.ui.utils.expandedShape @Composable -fun LicenseItem( +internal fun LicenseItem( licenseId: String ) = Box { var open by rememberSaveable { mutableStateOf(false) } - - TagItem( - icon = R.drawable.file_certificate, - onClick = { open = true } - ) - if (open) { ModalBottomSheet( onDismissRequest = { open = false }, @@ -52,4 +46,9 @@ fun LicenseItem( ) } } + + TagItem( + icon = R.drawable.file_certificate, + onClick = { open = true } + ) } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TagItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TagItem.kt index a2208d72..001036b2 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TagItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/items/TagItem.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp @Composable -fun TagItem( +internal fun TagItem( @DrawableRes icon: Int, onClick: () -> Unit ) = FilledTonalIconButton( diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt index 3c193a3b..a709b306 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/repository/view/pages/AboutPage.kt @@ -29,7 +29,7 @@ import dev.sanmer.mrepo.model.online.OnlineModule import dev.sanmer.mrepo.utils.extensions.openUrl @Composable -fun AboutPage( +internal fun AboutPage( online: OnlineModule ) = Column( modifier = Modifier 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 ece45240..22a7f546 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 @@ -38,7 +38,7 @@ import dev.sanmer.mrepo.model.online.VersionItem import dev.sanmer.mrepo.utils.extensions.toDateTime @Composable -fun OverviewPage( +internal fun OverviewPage( online: OnlineModule, item: VersionItem?, local: LocalModule?, @@ -63,6 +63,7 @@ fun OverviewPage( ) Spacer(modifier = Modifier.height(8.dp)) + Text( text = online.description, style = MaterialTheme.typography.bodyMedium, 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 0a04d9f7..6d258235 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 @@ -36,7 +36,7 @@ import dev.sanmer.mrepo.utils.extensions.toDate import kotlinx.coroutines.flow.Flow @Composable -fun VersionsPage( +internal fun VersionsPage( versions: List>, localVersionCode: Int, isProviderAlive: Boolean, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/AppThemeItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/AppThemeItem.kt index 1a6b503b..867455e0 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/AppThemeItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/AppThemeItem.kt @@ -23,7 +23,7 @@ import dev.sanmer.mrepo.ui.component.SettingNormalItem import dev.sanmer.mrepo.ui.utils.expandedShape @Composable -fun AppThemeItem( +internal fun AppThemeItem( themeColor: Int, darkMode: DarkMode, isDarkMode: Boolean, @@ -31,24 +31,23 @@ fun AppThemeItem( onDarkModeChange: (DarkMode) -> Unit ) { var open by rememberSaveable { mutableStateOf(false) } - - SettingNormalItem( - icon = R.drawable.color_swatch, - title = stringResource(id = R.string.settings_app_theme), - desc = stringResource(id = R.string.settings_app_theme_desc), - onClick = { open = true } - ) - if (open) { BottomSheet( onClose = { open = false }, themeColor = themeColor, darkMode = darkMode, isDarkMode = isDarkMode, - onThemeColorChange =onThemeColorChange, + onThemeColorChange = onThemeColorChange, onDarkModeChange = onDarkModeChange ) } + + SettingNormalItem( + icon = R.drawable.color_swatch, + title = stringResource(id = R.string.settings_app_theme), + desc = stringResource(id = R.string.settings_app_theme_desc), + onClick = { open = true } + ) } @Composable diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DarkModeItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DarkModeItem.kt index 5c5a0480..5a55dc5f 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DarkModeItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DarkModeItem.kt @@ -21,6 +21,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.surfaceColorAtElevation 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 @@ -65,7 +66,7 @@ private val modes = listOf( ) @Composable -fun DarkModeItem( +internal fun DarkModeItem( darkMode: DarkMode, onChange: (DarkMode) -> Unit ) = LazyRow( @@ -78,10 +79,9 @@ fun DarkModeItem( ) { DarkModeItem( item = it, - darkMode = darkMode - ) { value -> - onChange(value) - } + darkMode = darkMode, + onChange = onChange, + ) } } @@ -89,21 +89,21 @@ fun DarkModeItem( private fun DarkModeItem( item: DarkModeItem, darkMode: DarkMode, - onClick: (DarkMode) -> Unit + onChange: (DarkMode) -> Unit ) { - val selected = item.value == darkMode + val selected by remember { derivedStateOf { item.value == darkMode } } Box( modifier = Modifier .clip(RoundedCornerShape(15.dp)) .clickable( - onClick = { onClick(item.value) }, + onClick = { onChange(item.value) }, indication = null, interactionSource = remember { MutableInteractionSource() } ) .background(color = MaterialTheme.colorScheme.surfaceColorAtElevation(6.dp)), contentAlignment = Alignment.Center - ){ + ) { Row( modifier = Modifier.padding(all = 12.dp), verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt index 469c22f1..c6332d0b 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt @@ -19,12 +19,12 @@ import dev.sanmer.mrepo.ui.component.TextFieldDialog import java.io.File @Composable -fun DownloadPathItem( +internal fun DownloadPathItem( downloadPath: File, onChange: (File) -> Unit ) { var edit by remember { mutableStateOf(false) } - if (edit) OpenDocumentTreeDialog( + if (edit) EditDialog( path = downloadPath, onClose = { edit = false }, onConfirm = { if (it != downloadPath) onChange(it) } @@ -39,7 +39,7 @@ fun DownloadPathItem( } @Composable -private fun OpenDocumentTreeDialog( +private fun EditDialog( path : File, onClose: () -> Unit, onConfirm: (File) -> Unit diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/ThemePaletteItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/ThemePaletteItem.kt index 574db95b..739abd3a 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/ThemePaletteItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/ThemePaletteItem.kt @@ -2,7 +2,6 @@ package dev.sanmer.mrepo.ui.screens.settings.app.items import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -18,6 +17,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.surfaceColorAtElevation 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 @@ -29,35 +30,31 @@ import dev.sanmer.mrepo.compat.BuildCompat import dev.sanmer.mrepo.ui.theme.Colors @Composable -fun ThemePaletteItem( +internal fun ThemePaletteItem( themeColor: Int, isDarkMode: Boolean, onChange: (Int) -> Unit +) = FlowRow( + modifier = Modifier.padding(horizontal = 18.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - FlowRow( - modifier = Modifier.padding(horizontal = 18.dp, vertical = 16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - if (BuildCompat.atLeastS) { - ThemeColorItem( - id = Colors.Dynamic.id, - themeColor = themeColor, - isDarkMode = isDarkMode - ) { - onChange(it) - } - } + if (BuildCompat.atLeastS) { + ThemeColorItem( + id = Colors.Dynamic.id, + themeColor = themeColor, + isDarkMode = isDarkMode, + onChange = onChange + ) + } - Colors.getColorIds().forEach { - ThemeColorItem( - id = it, - themeColor = themeColor, - isDarkMode = isDarkMode - ) { value -> - onChange(value) - } - } + Colors.colorIds.forEach { + ThemeColorItem( + id = it, + themeColor = themeColor, + isDarkMode = isDarkMode, + onChange = onChange + ) } } @@ -66,19 +63,24 @@ private fun ThemeColorItem( id: Int, themeColor: Int, isDarkMode: Boolean, - onClick: (Int) -> Unit + onChange: (Int) -> Unit ) { + val selected by remember { derivedStateOf { id == themeColor } } val color = Colors.getColor(id) - val colorScheme = if (isDarkMode) color.darkColorScheme else color.lightColorScheme - val selected = id == themeColor + val colorScheme by remember { + derivedStateOf { + when { + isDarkMode -> color.darkColorScheme + else -> color.lightColorScheme + } + } + } Box( modifier = Modifier .clip(RoundedCornerShape(15.dp)) .clickable( - onClick = { onClick(id) }, - indication = null, - interactionSource = remember { MutableInteractionSource() } + onClick = { onChange(id) } ) .background( color = colorScheme.surfaceColorAtElevation(3.dp) diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/NonRootItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/NonRootItem.kt index 61be5321..44c08d8c 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/NonRootItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/NonRootItem.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R @Composable -fun NonRootItem() = Surface( +internal fun NonRootItem() = Surface( modifier = Modifier.padding(all = 18.dp), shape = RoundedCornerShape(15.dp), color = MaterialTheme.colorScheme.secondaryContainer diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/RootItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/RootItem.kt index a056174b..97da60f2 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/RootItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/items/RootItem.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R @Composable -fun RootItem( +internal fun RootItem( isAlive: Boolean, version: String ) = Surface( @@ -66,7 +66,8 @@ fun RootItem( Text( text = if (isAlive) { - stringResource(id = R.string.settings_root_provider, version) + stringResource(id = R.string.settings_root_provider, + version) } else { stringResource(id = R.string.settings_root_provider, stringResource(id = R.string.settings_root_not_available)) 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 f83159e8..7f69cb65 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 dev.sanmer.mrepo.R import dev.sanmer.mrepo.database.entity.online.RepoEntity @Composable -fun RepositoriesList( +internal fun RepositoriesList( list: List, state: LazyListState, insert: (RepoEntity) -> Unit, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt index 4a994d3b..5f8b41f8 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/repositories/RepositoriesScreen.kt @@ -160,7 +160,6 @@ private fun AddDialog( onAdd: (String) -> Unit ) { var domain by remember { mutableStateOf("") } - val onDone: () -> Unit = { onAdd("https://${domain}/") onClose() 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 bdb1a03b..dc029565 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 @@ -41,7 +41,7 @@ import dev.sanmer.mrepo.utils.extensions.shareText import dev.sanmer.mrepo.utils.extensions.toDateTime @Composable -fun RepositoryItem( +internal fun RepositoryItem( repo: RepoEntity, toggle: (Boolean) -> Unit, onUpdate: () -> Unit, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeItem.kt index 8c04363d..8bb08923 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeItem.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/workingmode/WorkingModeItem.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.unit.dp import dev.sanmer.mrepo.R @Composable -fun WorkingModeItem( +internal fun WorkingModeItem( title: String, desc: String, modifier: Modifier = Modifier, diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/theme/Colors.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/theme/Colors.kt index 4e13371b..1634426e 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/theme/Colors.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/theme/Colors.kt @@ -77,18 +77,20 @@ sealed class Colors( ) companion object { - private val mColors get() = listOf( - Pourville, - SoleilLevant, - Jeufosse, - PoppyField, - AlmondBlossom, - PlainAuvers, - WildRoses - ) + val colors by lazy { + listOf( + Pourville, + SoleilLevant, + Jeufosse, + PoppyField, + AlmondBlossom, + PlainAuvers, + WildRoses + ) + } - fun getColorIds(): List { - return mColors.map { it.id } + val colorIds by lazy { + colors.map { it.id } } @Composable @@ -98,7 +100,7 @@ sealed class Colors( return if (BuildCompat.atLeastS && id == Dynamic.id) { Dynamic(context) } else { - mColors[id] + colors[id] } } } diff --git a/app/src/main/res/drawable/arrow_badge_down.xml b/app/src/main/res/drawable/arrow_badge_down.xml new file mode 100644 index 00000000..c0625b27 --- /dev/null +++ b/app/src/main/res/drawable/arrow_badge_down.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/arrow_badge_up.xml b/app/src/main/res/drawable/arrow_badge_up.xml new file mode 100644 index 00000000..1834a304 --- /dev/null +++ b/app/src/main/res/drawable/arrow_badge_up.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/home.xml b/app/src/main/res/drawable/home.xml new file mode 100644 index 00000000..bdff11d2 --- /dev/null +++ b/app/src/main/res/drawable/home.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/app/src/main/res/drawable/world_www.xml b/app/src/main/res/drawable/world_www.xml deleted file mode 100644 index 1bd2e213..00000000 --- a/app/src/main/res/drawable/world_www.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 4c40e87b..5eeb27e3 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -41,8 +41,6 @@ حذف "%d إضافات" اضافة مستودع - اضافة - ملاحظة إلغاء حسناً تم التنزيل بنجاح @@ -77,9 +75,6 @@ الصفحة الرئيسية الرمز المصدري الدعم - عرض المسار - النوع: %s - مضاف في : %s المحدثه مؤخرا محدث في: %s القائمة المتقدمة diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 08995c6b..21bd84fe 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -32,10 +32,7 @@ Installieren Webseite Unterstützen - Typ: %s - Hinzugefügt am: %s %1$s von %2$s - Track ansehen Einstellungen der MRepo App selbst Magisk Modul Repositories anpassen Über @@ -61,9 +58,7 @@ Aktualisiert am: %s Löschen Repository hinzufügen - Hinzufügen Füge Modul Repositories hinzu und manage Module für Magisk und KernelSU. - Achtung Abbrechen Erweitertes Menü Zuletzt geupdated diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 50709d2b..d3404f44 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -44,8 +44,6 @@ Eliminar ¿Estás seguro de eliminarlo %s\? Agregar repositorio - Agregar - Atención Cancelar OK Descarga con éxito @@ -58,9 +56,6 @@ Página de inicio Código fuente Soporte - Ver origen - Tipo: %s - Añadido: %s Acerca de… Hecho con ❤️ por %s Descendente diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 0fe3a42d..9d8e4702 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -44,8 +44,6 @@ Supprimer Êtes-vous sûr de supprimer %s \? ajouter dépôt - Ajouter - Attention Annuler OK téléchargement réussi @@ -71,5 +69,4 @@ Page d\'accueil Code source Support - Ajouté à : %s \ No newline at end of file diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 7206714c..2906ef06 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -1,7 +1,6 @@ सम्पूर्ण - सावधान उचित हैं संलेख सहेजा गया नया @@ -58,9 +57,6 @@ दूरसंचारित स्त्रोत लेख सहायता - पथ देखे - प्रकार: %s - %s: पर योगित सूचित क्या आप इस भाग के इस संस्करण को अधिभारित अथवा संस्थापित करना चाहते हैं? गृहस्थान @@ -78,7 +74,6 @@ अनुपलब्ध मेजिस्क के भागों के कोषों को व्यवस्थित करें संस्थापन सफल होने के पश्चात संपीडित भाग (माॅडयूल) को हटाएं, यह उच्चतम शक्ति उपयोगकर्ता (सुपरयुजर) द्वारा संचालित होगा - नया मिलाएं %s के द्वारा ❤️ से निर्मित रद्द करें अभिधारण पथ diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 4aa737f8..58844ad8 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -54,11 +54,9 @@ Apakah Anda ingin memasang atau men-download modul versi ini\? Palet Tema Tambah repositori - Tambah Versi %1$s (%2$s) Menyediakan repositori modul dan Mengelola modul untuk Magisk dan KernelSU. Dibuat dengan ❤️ oleh %s - Perhatian Batal Oke Download berhasil @@ -72,9 +70,6 @@ Homepage Source Code Dukungan - Lihat Track - Jenis: %s - Ditambahkan pada: %s Tampilkan Ikon Diperbarui pada: %s Menu Lanjutan diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index adcd9948..29abf859 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -36,9 +36,7 @@ Homepage Codice Sorgente Supporto - Visualizza Traccia Nessun modulo trovato - Aggiunto il: %s %1$s di %2$s Rimuovi Ripristina @@ -58,7 +56,6 @@ Impossibile salvare: %s La repository è vuota Notifica - Tipo: %s Impostazioni di MRepo Tema App Percorso per i Download @@ -74,10 +71,8 @@ Elimina Sei sicuro di voler eliminare %s? Aggiungi repository - Aggiungi Versione %1$s (%2$s) Realizzato con il ❤️ da %s - Attenzione Cancella OK Menù Avanzato diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 8279e3a8..4ddc58f6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -23,8 +23,6 @@ 復元 リポジトリ 自動 - 注意 - 追加 機能が制限されています ダウンロード場所 ダークテーマ @@ -71,8 +69,6 @@ ホームページ ソースコード サポート - タイプ: %s - 追加日: %s %1$s — %2$s なし このアプリについて diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 9bebc10c..f2919090 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -53,11 +53,9 @@ Usuń Usunąć %s\? Dodaj repozytorium - Dodaj Wersja %1$s (%2$s) Zarządza repozytoriami, modułami Magisk i KernelSU. Stworzone z ❤️ przez %s - Uwaga Anuluj OK Pobieranie zakończone sukcesem @@ -71,9 +69,6 @@ Zaktualizowano Strona domowa Wsparcie - Zobacz ścieżkę - Typ: %s - Dodano w: %s Pokaż czas aktualizacji Nazwa Czas aktualizacji diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 54914382..d6c975a2 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -43,8 +43,6 @@ Apagar Você tem certeza de que gostaria de apagar %s\? Adicionar repositório - Adicionar - Atenção Cancelar Ok Download com sucesso diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 23d42c15..dc821dd1 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -44,8 +44,6 @@ Șterge Sigur ștergi %s\? Adaugă un depozit - Adaugă - Atenție Anulează OK Descărcare reușită @@ -67,7 +65,6 @@ Versiunea %1$s (%2$s) Gestionează module și furnizează depozite de module pentru Magisk și KernelSU. Făcut cu ❤️ de %s - Adăugat la: %s Fixare instalate Afișare pictogramă Afișare licență @@ -85,8 +82,6 @@ Cod sursă Pagina web Suport - Vizualizare cale - Tip: %s Data actualizării Notifică Ignoră diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 3ea986ca..6c2b4e94 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -60,11 +60,9 @@ Убрать Вы уверены что хотите удалить %s\? Добавить репозиторий - Добавить Версия %1$s (%2$s) Предоставление репозиториев модулей и управление модулями для Magisk и KernelSU. Сделано с ❤️ %s - Внимание Отменить Поиск… Облако @@ -77,9 +75,6 @@ Пин-код обновлён Показать иконку Показать лицензию - Просмотр трека - Тип: %s - Добавлено: %s Обновлено: %s Расширенное меню Режим сортировки diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 94aa84d0..cf1dac44 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -51,11 +51,9 @@ Sil Repo ekle %s silmek istediğinizden emin misiniz\? - Ekle Sürüm %1$s (%2$s) Magisk ve KernelSU için modül repoları sağlayın ve modülleri yönetin. %s tarafından ❤️ ile yapılmıştır - Dikkat İptal Tamam İndirme başarılı @@ -72,9 +70,6 @@ Anaysayfa Kaynak kodu Destek - İzi görüntüle - Tip: %s - %s tarihinde eklendi Yüklenenleri sabitle Güncellenebilir olanları sabitle Simge göster diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index aa26b27f..cbad83fa 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -32,7 +32,6 @@ Trang chủ Mã nguồn Ủng hộ - Loại: %s Loại bỏ Khôi phục Cài đặt @@ -40,8 +39,6 @@ Cập nhật Ứng dụng %1$s bởi %2$s - Đã thêm lúc: %s - Hiển thị theo dõi Kho lưu trữ Quản lý kho mô-đun Magisk Về @@ -65,11 +62,9 @@ Đã cập nhật lúc: %s Bạn có chắc chắn xóa %s không\? Thêm kho lưu trữ - Thêm Phiên bản %1$s (%2$s) Cung cấp kho mô-đun và Quản lý mô-đun cho Magisk và KernelSU. Được làm với ❤️ bởi %s - Chú ý Hủy bỏ OK Thực đơn nâng cao diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 735588ca..e7ef62e3 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -51,9 +51,6 @@ 主页 源码 支持 - 追踪信息 - 类型: %s - 添加于: %s 没找到任何模块 @@ -95,16 +92,14 @@ 更新于: %s 更新 删除 - 你确定要删除 %s? + 你想要删除这个存储库吗? 添加存储库 - 添加 版本 %1$s (%2$s) 为 Magisk 和 KernelSU 提供模块存储库以及模块管理. 由 %s 用 ❤️ 制作 - 注意 取消 确定 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index ac090f8c..65e7c338 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -56,11 +56,9 @@ 刪除 你確定要刪除 %s? 新增儲存庫 - 新增 版本 %1$s (%2$s) 為 Magisk 和 KernelSU 提供模組儲存庫以及模組管理。 由 %s 用 ❤️ 製作 - 注意 取消 確定 下載成功 @@ -74,12 +72,9 @@ 新增 保存失敗:%s 支援 - 類型:%s - 檢視追蹤資料 顯示授權 主頁面 原始碼 - 新增於:%s 更新 排序模式 名稱 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 24d781cb..7521d643 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,9 +51,6 @@ Homepage Source code Support - View Track - Type: %s - Added at: %s No modules found @@ -96,16 +93,14 @@ Updated at: %s Update Delete - Are you sure to delete %s? + Do you want to delete this repo? Add Repository - Add Version %1$s (%2$s) - Provide modules repositories and Manage modules for Magisk and KernelSU. + Provide modules repositories and manage modules for Magisk and KernelSU. Made with ❤️ by %s - Attention Cancel OK