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 package app.revanced.manager.ui.screen
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth 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.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons 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.HelpOutline
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.remember 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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.pluralStringResource
@ -29,6 +33,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar 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.component.LoadingIndicator
import app.revanced.manager.ui.model.SelectedApp import app.revanced.manager.ui.model.SelectedApp
import app.revanced.manager.ui.viewmodel.VersionSelectorViewModel import app.revanced.manager.ui.viewmodel.VersionSelectorViewModel
@ -56,6 +61,8 @@ fun VersionSelectorScreen(
} }
} }
var selectedVersion: SelectedApp? by rememberSaveable { mutableStateOf(null) }
Scaffold( Scaffold(
topBar = { topBar = {
AppTopBar( AppTopBar(
@ -65,75 +72,95 @@ fun VersionSelectorScreen(
IconButton(onClick = { }) { IconButton(onClick = { }) {
Icon(Icons.Outlined.HelpOutline, stringResource(R.string.help)) 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 -> ) { paddingValues ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(paddingValues) .padding(paddingValues)
.fillMaxSize(), .fillMaxSize()
verticalArrangement = Arrangement.Center, .verticalScroll(rememberScrollState())
horizontalAlignment = Alignment.CenterHorizontally
) { ) {
when { viewModel.installedApp?.let { packageInfo ->
!viewModel.isDownloading && list.isNotEmpty() -> { SelectedApp.Installed(
Column( packageName = viewModel.packageName,
modifier = Modifier version = packageInfo.versionName
.fillMaxSize() ).let {
.verticalScroll(rememberScrollState()) SelectedAppItem(
) { selectedApp = it,
list.forEach { selectedApp -> selected = selectedVersion == it,
ListItem( onClick = { selectedVersion = it },
modifier = Modifier.clickable { onAppClick(selectedApp) }, patchCount = supportedVersions[it.version]
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.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(stringResource(R.string.error_occurred))
Text( Text(
text = viewModel.errorMessage!!, text = viewModel.errorMessage!!,
modifier = Modifier.padding(horizontal = 15.dp) 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 package app.revanced.manager.ui.viewmodel
import android.content.pm.PackageInfo
import android.util.Log import android.util.Log
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf 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.APKMirror
import app.revanced.manager.network.downloader.AppDownloader import app.revanced.manager.network.downloader.AppDownloader
import app.revanced.manager.ui.model.SelectedApp import app.revanced.manager.ui.model.SelectedApp
import app.revanced.manager.util.PM
import app.revanced.manager.util.mutableStateSetOf import app.revanced.manager.util.mutableStateSetOf
import app.revanced.manager.util.simpleMessage import app.revanced.manager.util.simpleMessage
import app.revanced.manager.util.tag import app.revanced.manager.util.tag
@ -20,16 +22,17 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.get import org.koin.core.component.inject
class VersionSelectorViewModel( class VersionSelectorViewModel(
val packageName: String val packageName: String
) : ViewModel(), KoinComponent { ) : ViewModel(), KoinComponent {
private val downloadedAppRepository: DownloadedAppRepository = get() private val downloadedAppRepository: DownloadedAppRepository by inject()
private val sourceRepository: SourceRepository = get() private val sourceRepository: SourceRepository by inject()
private val pm: PM by inject()
private val appDownloader: AppDownloader = APKMirror() private val appDownloader: AppDownloader = APKMirror()
var isDownloading: Boolean by mutableStateOf(false) var installedApp: PackageInfo? by mutableStateOf(null)
private set private set
var isLoading by mutableStateOf(true) var isLoading by mutableStateOf(true)
private set private set
@ -63,6 +66,10 @@ class VersionSelectorViewModel(
} }
init { init {
viewModelScope.launch(Dispatchers.Main) {
installedApp = withContext(Dispatchers.IO) { pm.getPackageInfo(packageName) }
}
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
val compatibleVersions = supportedVersions.first() val compatibleVersions = supportedVersions.first()

View File

@ -131,6 +131,7 @@
<string name="loading">Loading…</string> <string name="loading">Loading…</string>
<string name="not_installed">Not installed</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="already_downloaded">Already downloaded</string>
<string name="select_file">Select file</string> <string name="select_file">Select file</string>