mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2024-11-10 01:01:56 +01:00
feat: Collapse ExtendedFAB on scroll (#1630)
This commit is contained in:
parent
607d8b67c9
commit
39536c0e18
3 changed files with 79 additions and 29 deletions
|
@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
@ -69,6 +70,7 @@ import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW
|
|||
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_UNSUPPORTED
|
||||
import app.revanced.manager.util.Options
|
||||
import app.revanced.manager.util.PatchSelection
|
||||
import app.revanced.manager.util.isScrollingUp
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.compose.rememberKoinInject
|
||||
|
||||
|
@ -273,7 +275,7 @@ fun PatchesSelectorScreen(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
val patchLazyListState = rememberLazyListState()
|
||||
Scaffold(
|
||||
topBar = {
|
||||
AppTopBar(
|
||||
|
@ -302,6 +304,7 @@ fun PatchesSelectorScreen(
|
|||
ExtendedFloatingActionButton(
|
||||
text = { Text(stringResource(R.string.save)) },
|
||||
icon = { Icon(Icons.Outlined.Save, null) },
|
||||
expanded = patchLazyListState.isScrollingUp,
|
||||
onClick = {
|
||||
// TODO: only allow this if all required options have been set.
|
||||
onSave(vm.getCustomSelection(), vm.getOptions())
|
||||
|
@ -344,7 +347,8 @@ fun PatchesSelectorScreen(
|
|||
val bundle = bundles[index]
|
||||
|
||||
LazyColumnWithScrollbar(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = patchLazyListState
|
||||
) {
|
||||
patchList(
|
||||
uid = bundle.uid,
|
||||
|
|
|
@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.Row
|
|||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
|
@ -32,11 +34,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import app.revanced.manager.R
|
||||
import app.revanced.manager.data.room.apps.installed.InstallType
|
||||
import app.revanced.manager.ui.component.AppTopBar
|
||||
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||
import app.revanced.manager.ui.component.GroupHeader
|
||||
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
||||
import app.revanced.manager.ui.component.LoadingIndicator
|
||||
import app.revanced.manager.ui.model.SelectedApp
|
||||
import app.revanced.manager.ui.viewmodel.VersionSelectorViewModel
|
||||
import app.revanced.manager.util.isScrollingUp
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
@ -63,6 +66,7 @@ fun VersionSelectorScreen(
|
|||
|
||||
var selectedVersion: SelectedApp? by rememberSaveable { mutableStateOf(null) }
|
||||
|
||||
val lazyListState = rememberLazyListState()
|
||||
Scaffold(
|
||||
topBar = {
|
||||
AppTopBar(
|
||||
|
@ -74,38 +78,47 @@ fun VersionSelectorScreen(
|
|||
ExtendedFloatingActionButton(
|
||||
text = { Text(stringResource(R.string.select_version)) },
|
||||
icon = { Icon(Icons.Default.Check, null) },
|
||||
expanded = lazyListState.isScrollingUp,
|
||||
onClick = { selectedVersion?.let(onAppClick) }
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
ColumnWithScrollbar(
|
||||
LazyColumnWithScrollbar(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.fillMaxSize(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
state = lazyListState
|
||||
) {
|
||||
viewModel.installedApp?.let { (packageInfo, installedApp) ->
|
||||
SelectedApp.Installed(
|
||||
packageName = viewModel.packageName,
|
||||
version = packageInfo.versionName
|
||||
).let {
|
||||
SelectedAppItem(
|
||||
selectedApp = it,
|
||||
selected = selectedVersion == it,
|
||||
onClick = { selectedVersion = it },
|
||||
patchCount = supportedVersions[it.version],
|
||||
enabled =
|
||||
item {
|
||||
SelectedAppItem(
|
||||
selectedApp = it,
|
||||
selected = selectedVersion == it,
|
||||
onClick = { selectedVersion = it },
|
||||
patchCount = supportedVersions[it.version],
|
||||
enabled =
|
||||
!(installedApp?.installType == InstallType.ROOT && !viewModel.rootInstaller.hasRootAccess()),
|
||||
alreadyPatched = installedApp != null && installedApp.installType != InstallType.ROOT
|
||||
)
|
||||
alreadyPatched = installedApp != null && installedApp.installType != InstallType.ROOT
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row(Modifier.fillMaxWidth()) {
|
||||
GroupHeader(stringResource(R.string.downloadable_versions))
|
||||
item {
|
||||
Row(Modifier.fillMaxWidth()) {
|
||||
GroupHeader(stringResource(R.string.downloadable_versions))
|
||||
}
|
||||
}
|
||||
|
||||
list.forEach {
|
||||
items(
|
||||
items = list,
|
||||
key = { it.packageName }
|
||||
) {
|
||||
SelectedAppItem(
|
||||
selectedApp = it,
|
||||
selected = selectedVersion == it,
|
||||
|
@ -115,19 +128,23 @@ fun VersionSelectorScreen(
|
|||
}
|
||||
|
||||
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)
|
||||
)
|
||||
item {
|
||||
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 if (viewModel.isLoading) {
|
||||
item {
|
||||
LoadingIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,14 @@ import android.os.Build
|
|||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.Lifecycle
|
||||
|
@ -166,3 +174,24 @@ fun String.relativeTime(context: Context): String {
|
|||
return context.getString(R.string.invalid_date)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LazyListState.isScrollingUp(): State<Boolean> {
|
||||
return remember(this) {
|
||||
var previousIndex by mutableIntStateOf(firstVisibleItemIndex)
|
||||
var previousScrollOffset by mutableIntStateOf(firstVisibleItemScrollOffset)
|
||||
|
||||
derivedStateOf {
|
||||
if (previousIndex != firstVisibleItemIndex) {
|
||||
previousIndex > firstVisibleItemIndex
|
||||
} else {
|
||||
previousScrollOffset >= firstVisibleItemScrollOffset
|
||||
}.also {
|
||||
previousIndex = firstVisibleItemIndex
|
||||
previousScrollOffset = firstVisibleItemScrollOffset
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val LazyListState.isScrollingUp: Boolean @Composable get() = this.isScrollingUp().value
|
Loading…
Reference in a new issue