feat: improved compose stability

This commit is contained in:
CnC-Robert 2023-06-04 17:50:40 +02:00
parent 776d0d93d1
commit db07c5969e
No known key found for this signature in database
GPG Key ID: C58ED617AEA8CB68
8 changed files with 35 additions and 27 deletions

View File

@ -1,13 +1,16 @@
package app.revanced.manager.compose.domain.sources package app.revanced.manager.compose.domain.sources
import androidx.compose.runtime.Stable
import app.revanced.manager.compose.network.api.ManagerAPI import app.revanced.manager.compose.network.api.ManagerAPI
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.core.component.get import org.koin.core.component.get
import java.io.File import java.io.File
@Stable
class RemoteSource(id: Int, directory: File) : Source(id, directory) { class RemoteSource(id: Int, directory: File) : Source(id, directory) {
private val api: ManagerAPI = get() private val api: ManagerAPI = get()
suspend fun downloadLatest() = withContext(Dispatchers.IO) { suspend fun downloadLatest() = withContext(Dispatchers.IO) {
api.downloadBundle(patchesJar, integrations).also { (patchesVer, integrationsVer) -> api.downloadBundle(patchesJar, integrations).also { (patchesVer, integrationsVer) ->
saveVersion(patchesVer, integrationsVer) saveVersion(patchesVer, integrationsVer)

View File

@ -1,6 +1,7 @@
package app.revanced.manager.compose.domain.sources package app.revanced.manager.compose.domain.sources
import android.util.Log import android.util.Log
import androidx.compose.runtime.Stable
import app.revanced.manager.compose.patcher.patch.PatchBundle import app.revanced.manager.compose.patcher.patch.PatchBundle
import app.revanced.manager.compose.domain.repository.SourcePersistenceRepository import app.revanced.manager.compose.domain.repository.SourcePersistenceRepository
import app.revanced.manager.compose.util.tag import app.revanced.manager.compose.util.tag
@ -13,6 +14,7 @@ import java.io.File
/** /**
* A [PatchBundle] source. * A [PatchBundle] source.
*/ */
@Stable
sealed class Source(val id: Int, directory: File) : KoinComponent { sealed class Source(val id: Int, directory: File) : KoinComponent {
private val configRepository: SourcePersistenceRepository by inject() private val configRepository: SourcePersistenceRepository by inject()
protected companion object { protected companion object {

View File

@ -1,6 +1,6 @@
package app.revanced.manager.compose.patcher.patch package app.revanced.manager.compose.patcher.patch
import android.os.Parcelable import androidx.compose.runtime.Immutable
import app.revanced.manager.compose.patcher.PatchClass import app.revanced.manager.compose.patcher.PatchClass
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
@ -10,24 +10,24 @@ import app.revanced.patcher.extensions.PatchExtensions.include
import app.revanced.patcher.extensions.PatchExtensions.options import app.revanced.patcher.extensions.PatchExtensions.options
import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.PatchOption import app.revanced.patcher.patch.PatchOption
import kotlinx.parcelize.Parcelize import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Parcelize
data class PatchInfo( data class PatchInfo(
val name: String, val name: String,
val description: String?, val description: String?,
val dependencies: List<String>?, val dependencies: ImmutableList<String>?,
val include: Boolean, val include: Boolean,
val compatiblePackages: List<CompatiblePackage>?, val compatiblePackages: ImmutableList<CompatiblePackage>?,
val options: List<Option>? val options: ImmutableList<Option>?
) : Parcelable { ) {
constructor(patch: PatchClass) : this( constructor(patch: PatchClass) : this(
patch.patchName, patch.patchName,
patch.description, patch.description,
patch.dependencies?.map { it.java.patchName }, patch.dependencies?.map { it.java.patchName }?.toImmutableList(),
patch.include, patch.include,
patch.compatiblePackages?.map { CompatiblePackage(it) }, patch.compatiblePackages?.map { CompatiblePackage(it) }?.toImmutableList(),
patch.options?.map { Option(it) }) patch.options?.map { Option(it) }?.toImmutableList())
fun compatibleWith(packageName: String) = compatiblePackages?.any { it.name == packageName } ?: true fun compatibleWith(packageName: String) = compatiblePackages?.any { it.name == packageName } ?: true
@ -36,12 +36,14 @@ data class PatchInfo(
?: true ?: true
} }
@Parcelize @Immutable
data class CompatiblePackage(val name: String, val versions: List<String>) : Parcelable { data class CompatiblePackage(
constructor(pkg: Package) : this(pkg.name, pkg.versions.toList()) val name: String,
val versions: ImmutableList<String>
) {
constructor(pkg: Package) : this(pkg.name, pkg.versions.toList().toImmutableList())
} }
@Parcelize data class Option(val title: String, val key: String, val description: String, val required: Boolean) {
data class Option(val title: String, val key: String, val description: String, val required: Boolean) : Parcelable {
constructor(option: PatchOption<*>) : this(option.title, option.key, option.description, option.required) constructor(option: PatchOption<*>) : this(option.title, option.key, option.description, option.required)
} }

View File

@ -6,6 +6,9 @@ import androidx.work.Data
import androidx.work.workDataOf import androidx.work.workDataOf
import app.revanced.manager.compose.R import app.revanced.manager.compose.R
import app.revanced.manager.compose.patcher.Session import app.revanced.manager.compose.patcher.Session
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -31,7 +34,7 @@ enum class StepStatus {
class Step(val name: String, val status: StepStatus = StepStatus.WAITING) class Step(val name: String, val status: StepStatus = StepStatus.WAITING)
@Serializable @Serializable
class StepGroup(@StringRes val name: Int, val steps: List<Step>, val status: StepStatus = StepStatus.WAITING) class StepGroup(@StringRes val name: Int, val steps: ImmutableList<Step>, val status: StepStatus = StepStatus.WAITING)
class PatcherProgressManager(context: Context, selectedPatches: List<String>) { class PatcherProgressManager(context: Context, selectedPatches: List<String>) {
val stepGroups = generateGroupsList(context, selectedPatches) val stepGroups = generateGroupsList(context, selectedPatches)
@ -53,18 +56,18 @@ class PatcherProgressManager(context: Context, selectedPatches: List<String>) {
fun generateGroupsList(context: Context, selectedPatches: List<String>) = mutableListOf( fun generateGroupsList(context: Context, selectedPatches: List<String>) = mutableListOf(
StepGroup( StepGroup(
R.string.patcher_step_group_prepare, R.string.patcher_step_group_prepare,
listOf( persistentListOf(
Step(context.getString(R.string.patcher_step_unpack)), Step(context.getString(R.string.patcher_step_unpack)),
Step(context.getString(R.string.patcher_step_integrations)) Step(context.getString(R.string.patcher_step_integrations))
) )
), ),
StepGroup( StepGroup(
R.string.patcher_step_group_patching, R.string.patcher_step_group_patching,
selectedPatches.map { Step(it) } selectedPatches.map { Step(it) }.toImmutableList()
), ),
StepGroup( StepGroup(
R.string.patcher_step_group_saving, R.string.patcher_step_group_saving,
listOf(Step(context.getString(R.string.patcher_step_write_patched))) persistentListOf(Step(context.getString(R.string.patcher_step_write_patched)))
) )
) )
@ -95,7 +98,7 @@ class PatcherProgressManager(context: Context, selectedPatches: List<String>) {
StepGroup(group.name, group.steps.toMutableList().mutateIndex(key.stepIndex) { step -> StepGroup(group.name, group.steps.toMutableList().mutateIndex(key.stepIndex) { step ->
Step(step.name, newStatus) Step(step.name, newStatus)
}, newGroupStatus) }.toImmutableList(), newGroupStatus)
} }
val isFinalStep = isLastStepOfGroup && key.groupIndex == stepGroups.size - 1 val isFinalStep = isLastStepOfGroup && key.groupIndex == stepGroups.size - 1

View File

@ -25,7 +25,6 @@ import androidx.compose.material.icons.filled.BatteryAlert
import androidx.compose.material.icons.outlined.* import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -41,14 +40,12 @@ import app.revanced.manager.compose.ui.component.AppTopBar
import app.revanced.manager.compose.ui.destination.SettingsDestination import app.revanced.manager.compose.ui.destination.SettingsDestination
import app.revanced.manager.compose.ui.screen.settings.* import app.revanced.manager.compose.ui.screen.settings.*
import app.revanced.manager.compose.ui.viewmodel.SettingsViewModel import app.revanced.manager.compose.ui.viewmodel.SettingsViewModel
import app.revanced.manager.compose.ui.viewmodel.UpdateSettingsViewModel
import dev.olshevski.navigation.reimagined.* import dev.olshevski.navigation.reimagined.*
import org.koin.androidx.compose.getViewModel import org.koin.androidx.compose.getViewModel
@SuppressLint("BatteryLife") @SuppressLint("BatteryLife")
@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class)
@Composable @Composable
@Stable
fun SettingsScreen( fun SettingsScreen(
onBackClick: () -> Unit, onBackClick: () -> Unit,
viewModel: SettingsViewModel = getViewModel() viewModel: SettingsViewModel = getViewModel()

View File

@ -1,6 +1,5 @@
package app.revanced.manager.compose.ui.screen.settings package app.revanced.manager.compose.ui.screen.settings
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -26,7 +25,6 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -45,7 +43,7 @@ import dev.olshevski.navigation.reimagined.NavController
import dev.olshevski.navigation.reimagined.navigate import dev.olshevski.navigation.reimagined.navigate
import org.koin.androidx.compose.getViewModel import org.koin.androidx.compose.getViewModel
@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun UpdatesSettingsScreen( fun UpdatesSettingsScreen(
onBackClick: () -> Unit, onBackClick: () -> Unit,
@ -142,7 +140,6 @@ fun UpdateNotification(
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@Stable
fun UpdateProgressScreen( fun UpdateProgressScreen(
onBackClick: () -> Unit, onBackClick: () -> Unit,
vm: UpdateSettingsViewModel = getViewModel() vm: UpdateSettingsViewModel = getViewModel()

View File

@ -7,6 +7,7 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -32,6 +33,7 @@ import org.koin.core.component.inject
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files
@Stable
class InstallerViewModel( class InstallerViewModel(
input: AppInfo, input: AppInfo,
selectedPatches: PatchesSelection selectedPatches: PatchesSelection

View File

@ -1,5 +1,6 @@
package app.revanced.manager.compose.ui.viewmodel package app.revanced.manager.compose.ui.viewmodel
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -13,6 +14,7 @@ import kotlinx.coroutines.flow.map
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.get import org.koin.core.component.get
@Stable
class PatchesSelectorViewModel(appInfo: AppInfo) : ViewModel(), KoinComponent { class PatchesSelectorViewModel(appInfo: AppInfo) : ViewModel(), KoinComponent {
val bundlesFlow = get<SourceRepository>().bundles.map { bundles -> val bundlesFlow = get<SourceRepository>().bundles.map { bundles ->
bundles.mapValues { (_, bundle) -> bundle.patches }.map { (name, patches) -> bundles.mapValues { (_, bundle) -> bundle.patches }.map { (name, patches) ->