mirror of
https://github.com/revanced/revanced-manager
synced 2024-05-14 13:56:57 +02:00
feat: show installed app in version selector
This commit is contained in:
parent
aec8cec9b8
commit
61de0b67fa
@ -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,47 +72,48 @@ 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(),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
when {
|
|
||||||
!viewModel.isDownloading && list.isNotEmpty() -> {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
list.forEach { selectedApp ->
|
viewModel.installedApp?.let { packageInfo ->
|
||||||
ListItem(
|
SelectedApp.Installed(
|
||||||
modifier = Modifier.clickable { onAppClick(selectedApp) },
|
packageName = viewModel.packageName,
|
||||||
headlineContent = { Text(selectedApp.version) },
|
version = packageInfo.versionName
|
||||||
supportingContent =
|
).let {
|
||||||
if (selectedApp is SelectedApp.Local) {
|
SelectedAppItem(
|
||||||
{ Text(stringResource(R.string.already_downloaded)) }
|
selectedApp = it,
|
||||||
} else null,
|
selected = selectedVersion == it,
|
||||||
trailingContent = supportedVersions[selectedApp.version]?.let { {
|
onClick = { selectedVersion = it },
|
||||||
Text(
|
patchCount = supportedVersions[it.version]
|
||||||
pluralStringResource(
|
|
||||||
R.plurals.patches_count,
|
|
||||||
count = it,
|
|
||||||
it
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GroupHeader("Downloadable versions")
|
||||||
|
|
||||||
|
list.forEach {
|
||||||
|
SelectedAppItem(
|
||||||
|
selectedApp = it,
|
||||||
|
selected = selectedVersion == it,
|
||||||
|
onClick = { selectedVersion = it },
|
||||||
|
patchCount = supportedVersions[it.version]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewModel.errorMessage != null) {
|
if (viewModel.errorMessage != null) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@ -119,21 +127,40 @@ fun VersionSelectorScreen(
|
|||||||
}
|
}
|
||||||
} else if (viewModel.isLoading)
|
} else if (viewModel.isLoading)
|
||||||
LoadingIndicator()
|
LoadingIndicator()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.errorMessage != null -> {
|
|
||||||
Text(stringResource(R.string.error_occurred))
|
|
||||||
Text(
|
|
||||||
text = viewModel.errorMessage!!,
|
|
||||||
modifier = Modifier.padding(horizontal = 15.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
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()
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user