feat: show installed app in version selector

This commit is contained in:
CnC-Robert 2023-07-30 19:45:40 +02:00
parent aec8cec9b8
commit 61de0b67fa
3 changed files with 93 additions and 58 deletions

View file

@ -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)
)
}

View file

@ -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()

View file

@ -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>