mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2024-11-10 01:01:56 +01:00
feat: show installed app in version selector
This commit is contained in:
parent
aec8cec9b8
commit
61de0b67fa
3 changed files with 93 additions and 58 deletions
|
@ -1,7 +1,6 @@
|
|||
package app.revanced.manager.ui.screen
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
@ -9,18 +8,23 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.outlined.Search
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
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.pluralStringResource
|
||||
|
@ -29,6 +33,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.ui.component.AppTopBar
|
||||
import app.revanced.manager.ui.component.GroupHeader
|
||||
import app.revanced.manager.ui.component.LoadingIndicator
|
||||
import app.revanced.manager.ui.model.SelectedApp
|
||||
import app.revanced.manager.ui.viewmodel.VersionSelectorViewModel
|
||||
|
@ -56,6 +61,8 @@ fun VersionSelectorScreen(
|
|||
}
|
||||
}
|
||||
|
||||
var selectedVersion: SelectedApp? by rememberSaveable { mutableStateOf(null) }
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
AppTopBar(
|
||||
|
@ -65,75 +72,95 @@ fun VersionSelectorScreen(
|
|||
IconButton(onClick = { }) {
|
||||
Icon(Icons.Outlined.HelpOutline, stringResource(R.string.help))
|
||||
}
|
||||
IconButton(onClick = { }) {
|
||||
Icon(Icons.Outlined.Search, stringResource(R.string.search))
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
ExtendedFloatingActionButton(
|
||||
text = { Text("Select version") },
|
||||
icon = { Icon(Icons.Default.Check, null) },
|
||||
onClick = { selectedVersion?.let(onAppClick) }
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
when {
|
||||
!viewModel.isDownloading && list.isNotEmpty() -> {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
list.forEach { selectedApp ->
|
||||
ListItem(
|
||||
modifier = Modifier.clickable { onAppClick(selectedApp) },
|
||||
headlineContent = { Text(selectedApp.version) },
|
||||
supportingContent =
|
||||
if (selectedApp is SelectedApp.Local) {
|
||||
{ Text(stringResource(R.string.already_downloaded)) }
|
||||
} else null,
|
||||
trailingContent = supportedVersions[selectedApp.version]?.let { {
|
||||
Text(
|
||||
pluralStringResource(
|
||||
R.plurals.patches_count,
|
||||
count = it,
|
||||
it
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
if (viewModel.errorMessage != null) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(stringResource(R.string.error_occurred))
|
||||
Text(
|
||||
text = viewModel.errorMessage!!,
|
||||
modifier = Modifier.padding(horizontal = 15.dp)
|
||||
)
|
||||
}
|
||||
} else if (viewModel.isLoading)
|
||||
LoadingIndicator()
|
||||
}
|
||||
viewModel.installedApp?.let { packageInfo ->
|
||||
SelectedApp.Installed(
|
||||
packageName = viewModel.packageName,
|
||||
version = packageInfo.versionName
|
||||
).let {
|
||||
SelectedAppItem(
|
||||
selectedApp = it,
|
||||
selected = selectedVersion == it,
|
||||
onClick = { selectedVersion = it },
|
||||
patchCount = supportedVersions[it.version]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.errorMessage != null -> {
|
||||
GroupHeader("Downloadable versions")
|
||||
|
||||
list.forEach {
|
||||
SelectedAppItem(
|
||||
selectedApp = it,
|
||||
selected = selectedVersion == it,
|
||||
onClick = { selectedVersion = it },
|
||||
patchCount = supportedVersions[it.version]
|
||||
)
|
||||
}
|
||||
|
||||
if (viewModel.errorMessage != null) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(stringResource(R.string.error_occurred))
|
||||
Text(
|
||||
text = viewModel.errorMessage!!,
|
||||
modifier = Modifier.padding(horizontal = 15.dp)
|
||||
)
|
||||
}
|
||||
} else if (viewModel.isLoading)
|
||||
LoadingIndicator()
|
||||
|
||||
else -> {
|
||||
LoadingIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const val alreadyPatched = false
|
||||
|
||||
@Composable
|
||||
fun SelectedAppItem(
|
||||
selectedApp: SelectedApp,
|
||||
selected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
patchCount: Int?
|
||||
) {
|
||||
ListItem(
|
||||
leadingContent = { RadioButton(selected, null) },
|
||||
headlineContent = { Text(selectedApp.version) },
|
||||
supportingContent = when (selectedApp) {
|
||||
is SelectedApp.Installed ->
|
||||
if (alreadyPatched) {
|
||||
{ Text("Already patched") }
|
||||
} else {
|
||||
{ Text("Installed") }
|
||||
}
|
||||
|
||||
is SelectedApp.Local -> {
|
||||
{ Text(stringResource(R.string.already_downloaded)) }
|
||||
}
|
||||
|
||||
else -> null
|
||||
},
|
||||
trailingContent = patchCount?.let { {
|
||||
Text(pluralStringResource(R.plurals.patches_count, it, it))
|
||||
} },
|
||||
modifier = Modifier.clickable(onClick = onClick)
|
||||
)
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package app.revanced.manager.ui.viewmodel
|
||||
|
||||
import android.content.pm.PackageInfo
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
@ -11,6 +12,7 @@ import app.revanced.manager.domain.repository.SourceRepository
|
|||
import app.revanced.manager.network.downloader.APKMirror
|
||||
import app.revanced.manager.network.downloader.AppDownloader
|
||||
import app.revanced.manager.ui.model.SelectedApp
|
||||
import app.revanced.manager.util.PM
|
||||
import app.revanced.manager.util.mutableStateSetOf
|
||||
import app.revanced.manager.util.simpleMessage
|
||||
import app.revanced.manager.util.tag
|
||||
|
@ -20,16 +22,17 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.get
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class VersionSelectorViewModel(
|
||||
val packageName: String
|
||||
) : ViewModel(), KoinComponent {
|
||||
private val downloadedAppRepository: DownloadedAppRepository = get()
|
||||
private val sourceRepository: SourceRepository = get()
|
||||
private val downloadedAppRepository: DownloadedAppRepository by inject()
|
||||
private val sourceRepository: SourceRepository by inject()
|
||||
private val pm: PM by inject()
|
||||
private val appDownloader: AppDownloader = APKMirror()
|
||||
|
||||
var isDownloading: Boolean by mutableStateOf(false)
|
||||
var installedApp: PackageInfo? by mutableStateOf(null)
|
||||
private set
|
||||
var isLoading by mutableStateOf(true)
|
||||
private set
|
||||
|
@ -63,6 +66,10 @@ class VersionSelectorViewModel(
|
|||
}
|
||||
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.Main) {
|
||||
installedApp = withContext(Dispatchers.IO) { pm.getPackageInfo(packageName) }
|
||||
}
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val compatibleVersions = supportedVersions.first()
|
||||
|
|
|
@ -131,6 +131,7 @@
|
|||
<string name="loading">Loading…</string>
|
||||
<string name="not_installed">Not installed</string>
|
||||
|
||||
<string name="error_occurred">An error occurred</string>
|
||||
<string name="already_downloaded">Already downloaded</string>
|
||||
|
||||
<string name="select_file">Select file</string>
|
||||
|
|
Loading…
Reference in a new issue