feat: Scrollbars (#1479)

This commit is contained in:
Ushie 2024-01-08 01:28:16 +03:00 committed by GitHub
parent f38b31a591
commit 36c8f59d6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 318 additions and 197 deletions

View File

@ -54,7 +54,7 @@ android {
includeInApk = false
includeInBundle = false
}
packaging {
resources.excludes.addAll(listOf(
"/prebuilt/**",
@ -164,4 +164,7 @@ dependencies {
// Fading Edges
implementation(libs.fading.edges)
// Scrollbars
implementation(libs.scrollbars)
}

View File

@ -0,0 +1,29 @@
package app.revanced.manager.ui.component
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
fun ColumnWithScrollbar(
modifier: Modifier = Modifier,
state: ScrollState = rememberScrollState(),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
content: @Composable ColumnScope.() -> Unit
) {
Column(
modifier = modifier.then(Modifier.verticalScroll(state)),
verticalArrangement = verticalArrangement,
horizontalAlignment = horizontalAlignment,
content = content
)
Scrollbar(state, Modifier.then(modifier.padding())) // Get the modifier's padding to maintain scrollbar within the screen, e.g. paddingValues
}

View File

@ -0,0 +1,42 @@
package app.revanced.manager.ui.component
import androidx.compose.foundation.gestures.FlingBehavior
import androidx.compose.foundation.gestures.ScrollableDefaults
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun LazyColumnWithScrollbar(
modifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
verticalArrangement: Arrangement.Vertical =
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
content: LazyListScope.() -> Unit
) {
LazyColumn(
modifier = modifier,
state = state,
contentPadding = contentPadding,
reverseLayout = reverseLayout,
verticalArrangement = verticalArrangement,
horizontalAlignment = horizontalAlignment,
flingBehavior = flingBehavior,
userScrollEnabled = userScrollEnabled,
content = content
)
Scrollbar(state, Modifier.then(modifier.padding())) // Get the modifier's padding to maintain scrollbar within the screen, e.g. paddingValues
}

View File

@ -0,0 +1,64 @@
package app.revanced.manager.ui.component
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.gigamole.composescrollbars.Scrollbars
import com.gigamole.composescrollbars.ScrollbarsState
import com.gigamole.composescrollbars.config.ScrollbarsConfig
import com.gigamole.composescrollbars.config.ScrollbarsOrientation
import com.gigamole.composescrollbars.config.layercontenttype.ScrollbarsLayerContentType
import com.gigamole.composescrollbars.config.layersType.ScrollbarsLayersType
import com.gigamole.composescrollbars.config.layersType.thicknessType.ScrollbarsThicknessType
import com.gigamole.composescrollbars.config.visibilitytype.ScrollbarsVisibilityType
import com.gigamole.composescrollbars.scrolltype.ScrollbarsScrollType
import com.gigamole.composescrollbars.scrolltype.knobtype.ScrollbarsDynamicKnobType
import com.gigamole.composescrollbars.scrolltype.knobtype.ScrollbarsStaticKnobType
@Composable
fun Scrollbar(scrollState: ScrollState, modifier: Modifier = Modifier) {
Scrollbar(
ScrollbarsScrollType.Scroll(
knobType = ScrollbarsStaticKnobType.Auto(),
state = scrollState
),
modifier
)
}
@Composable
fun Scrollbar(lazyListState: LazyListState, modifier: Modifier = Modifier) {
Scrollbar(
ScrollbarsScrollType.Lazy.List.Dynamic(
knobType = ScrollbarsDynamicKnobType.Auto(),
state = lazyListState
),
modifier
)
}
@Composable
private fun Scrollbar(scrollType: ScrollbarsScrollType, modifier: Modifier = Modifier) {
Scrollbars(
state = ScrollbarsState(
ScrollbarsConfig(
orientation = ScrollbarsOrientation.Vertical,
paddingValues = PaddingValues(0.dp),
layersType = ScrollbarsLayersType.Wrap(ScrollbarsThicknessType.Exact(4.dp)),
knobLayerContentType = ScrollbarsLayerContentType.Default.Colored.Idle(
idleColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.35f)
),
visibilityType = ScrollbarsVisibilityType.Dynamic.Fade(
isVisibleOnTouchDown = true,
isStaticWhenScrollPossible = false
)
),
scrollType
),
modifier = modifier
)
}

View File

@ -2,12 +2,9 @@ package app.revanced.manager.ui.component.bundle
import android.webkit.URLUtil
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
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.automirrored.outlined.ArrowRight
import androidx.compose.material3.FilledTonalButton
@ -25,6 +22,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.TextInputDialog
import app.revanced.manager.util.isDebuggable
@ -43,141 +41,142 @@ fun BaseBundleDialog(
onPatchesClick: () -> Unit,
onBundleTypeClick: () -> Unit = {},
extraFields: @Composable ColumnScope.() -> Unit = {}
) = Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
.padding(
start = 8.dp,
top = 8.dp,
end = 4.dp,
)
.then(modifier)
) {
var showNameInputDialog by rememberSaveable {
mutableStateOf(false)
}
if (showNameInputDialog) {
TextInputDialog(
initial = name,
title = stringResource(R.string.bundle_input_name),
onDismissRequest = {
showNameInputDialog = false
},
onConfirm = {
showNameInputDialog = false
onNameChange?.invoke(it)
},
validator = {
it.length in 1..19
}
)
}
BundleListItem(
headlineText = stringResource(R.string.bundle_input_name),
supportingText = name.ifEmpty { stringResource(R.string.field_not_set) },
modifier = Modifier.clickable(enabled = onNameChange != null) {
showNameInputDialog = true
}
)
remoteUrl?.takeUnless { isDefault }?.let { url ->
var showUrlInputDialog by rememberSaveable {
ColumnWithScrollbar(
modifier = Modifier
.fillMaxWidth()
.padding(
start = 8.dp,
top = 8.dp,
end = 4.dp,
)
.then(modifier)
) {
var showNameInputDialog by rememberSaveable {
mutableStateOf(false)
}
if (showUrlInputDialog) {
if (showNameInputDialog) {
TextInputDialog(
initial = url,
title = stringResource(R.string.bundle_input_source_url),
onDismissRequest = { showUrlInputDialog = false },
initial = name,
title = stringResource(R.string.bundle_input_name),
onDismissRequest = {
showNameInputDialog = false
},
onConfirm = {
showUrlInputDialog = false
onRemoteUrlChange?.invoke(it)
showNameInputDialog = false
onNameChange?.invoke(it)
},
validator = {
if (it.isEmpty()) return@TextInputDialog false
URLUtil.isValidUrl(it)
it.length in 1..19
}
)
}
BundleListItem(
modifier = Modifier.clickable(enabled = onRemoteUrlChange != null) {
showUrlInputDialog = true
},
headlineText = stringResource(R.string.bundle_input_source_url),
supportingText = url.ifEmpty { stringResource(R.string.field_not_set) }
headlineText = stringResource(R.string.bundle_input_name),
supportingText = name.ifEmpty { stringResource(R.string.field_not_set) },
modifier = Modifier.clickable(enabled = onNameChange != null) {
showNameInputDialog = true
}
)
}
extraFields()
remoteUrl?.takeUnless { isDefault }?.let { url ->
var showUrlInputDialog by rememberSaveable {
mutableStateOf(false)
}
if (showUrlInputDialog) {
TextInputDialog(
initial = url,
title = stringResource(R.string.bundle_input_source_url),
onDismissRequest = { showUrlInputDialog = false },
onConfirm = {
showUrlInputDialog = false
onRemoteUrlChange?.invoke(it)
},
validator = {
if (it.isEmpty()) return@TextInputDialog false
if (remoteUrl != null) {
BundleListItem(
headlineText = stringResource(R.string.automatically_update),
supportingText = stringResource(R.string.automatically_update_description),
trailingContent = {
Switch(
checked = autoUpdate,
onCheckedChange = onAutoUpdateChange
URLUtil.isValidUrl(it)
}
)
},
modifier = Modifier.clickable {
onAutoUpdateChange(!autoUpdate)
}
)
}
BundleListItem(
headlineText = stringResource(R.string.bundle_type),
supportingText = stringResource(R.string.bundle_type_description),
modifier = Modifier.clickable {
onBundleTypeClick()
}
) {
FilledTonalButton(
onClick = onBundleTypeClick,
content = {
if (remoteUrl == null) {
Text(stringResource(R.string.local))
} else {
Text(stringResource(R.string.remote))
}
}
)
}
if (version != null || patchCount > 0) {
Text(
text = stringResource(R.string.information),
modifier = Modifier.padding(
horizontal = 16.dp,
vertical = 12.dp
),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary,
)
}
val patchesClickable = LocalContext.current.isDebuggable && patchCount > 0
BundleListItem(
headlineText = stringResource(R.string.patches),
supportingText = if (patchCount == 0) stringResource(R.string.no_patches)
else stringResource(R.string.patches_available, patchCount),
modifier = Modifier.clickable(enabled = patchesClickable, onClick = onPatchesClick)
) {
if (patchesClickable)
Icon(
Icons.AutoMirrored.Outlined.ArrowRight,
stringResource(R.string.patches)
BundleListItem(
modifier = Modifier.clickable(enabled = onRemoteUrlChange != null) {
showUrlInputDialog = true
},
headlineText = stringResource(R.string.bundle_input_source_url),
supportingText = url.ifEmpty { stringResource(R.string.field_not_set) }
)
}
}
extraFields()
if (remoteUrl != null) {
BundleListItem(
headlineText = stringResource(R.string.automatically_update),
supportingText = stringResource(R.string.automatically_update_description),
trailingContent = {
Switch(
checked = autoUpdate,
onCheckedChange = onAutoUpdateChange
)
},
modifier = Modifier.clickable {
onAutoUpdateChange(!autoUpdate)
}
)
}
version?.let {
BundleListItem(
headlineText = stringResource(R.string.version),
supportingText = it,
)
headlineText = stringResource(R.string.bundle_type),
supportingText = stringResource(R.string.bundle_type_description),
modifier = Modifier.clickable {
onBundleTypeClick()
}
) {
FilledTonalButton(
onClick = onBundleTypeClick,
content = {
if (remoteUrl == null) {
Text(stringResource(R.string.local))
} else {
Text(stringResource(R.string.remote))
}
}
)
}
if (version != null || patchCount > 0) {
Text(
text = stringResource(R.string.information),
modifier = Modifier.padding(
horizontal = 16.dp,
vertical = 12.dp
),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary,
)
}
val patchesClickable = LocalContext.current.isDebuggable && patchCount > 0
BundleListItem(
headlineText = stringResource(R.string.patches),
supportingText = if (patchCount == 0) stringResource(R.string.no_patches)
else stringResource(R.string.patches_available, patchCount),
modifier = Modifier.clickable(enabled = patchesClickable, onClick = onPatchesClick)
) {
if (patchesClickable)
Icon(
Icons.AutoMirrored.Outlined.ArrowRight,
stringResource(R.string.patches)
)
}
version?.let {
BundleListItem(
headlineText = stringResource(R.string.version),
supportingText = it,
)
}
}
}

View File

@ -3,7 +3,6 @@ package app.revanced.manager.ui.component.bundle
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.Lightbulb
@ -27,6 +26,7 @@ import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import app.revanced.manager.R
import app.revanced.manager.domain.bundles.PatchBundleSource
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.NotificationCard
@OptIn(ExperimentalMaterial3Api::class)
@ -59,7 +59,7 @@ fun BundlePatchesDialog(
)
},
) { paddingValues ->
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier
.fillMaxWidth()
.padding(paddingValues)

View File

@ -3,7 +3,6 @@ package app.revanced.manager.ui.component.patches
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
@ -12,9 +11,9 @@ import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.outlined.Folder
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.ListItem
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -29,6 +28,7 @@ import androidx.compose.ui.window.DialogProperties
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.LazyColumnWithScrollbar
import app.revanced.manager.util.saver.PathSaver
import java.nio.file.Path
import kotlin.io.path.absolutePathString
@ -70,7 +70,7 @@ fun PathSelectorDialog(root: Path, onSelect: (Path?) -> Unit) {
currentDirectory = currentDirectory.parent
}
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier.padding(paddingValues)
) {
item(key = "current") {

View File

@ -4,7 +4,6 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
@ -28,6 +27,7 @@ import app.revanced.manager.R
import app.revanced.manager.ui.component.AppIcon
import app.revanced.manager.ui.component.AppLabel
import app.revanced.manager.ui.component.AppTopBar
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.AppSelectorViewModel
@ -88,13 +88,10 @@ fun AppSelectorScreen(
}
},
content = {
if (appList.isNotEmpty() && filterText.isNotEmpty()) {
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier.fillMaxSize()
) {
items(
items = filteredAppList,
key = { it.packageName }
@ -143,7 +140,6 @@ fun AppSelectorScreen(
)
}
}
}
)
}
@ -161,7 +157,7 @@ fun AppSelectorScreen(
)
}
) { paddingValues ->
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
@ -194,7 +190,6 @@ fun AppSelectorScreen(
items = appList,
key = { it.packageName }
) { app ->
ListItem(
modifier = Modifier.clickable { onAppClick(app.packageName) },
leadingContent = { AppIcon(app.packageInfo, null, Modifier.size(36.dp)) },

View File

@ -6,9 +6,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowRight
import androidx.compose.material.icons.automirrored.outlined.OpenInNew
@ -38,8 +36,9 @@ import app.revanced.manager.R
import app.revanced.manager.data.room.apps.installed.InstallType
import app.revanced.manager.ui.component.AppInfo
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.SegmentedButton
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.InstalledAppInfoViewModel
import app.revanced.manager.util.PatchesSelection
@ -70,11 +69,10 @@ fun InstalledAppInfoScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
) {
AppInfo(viewModel.appInfo) {
Text(viewModel.installedApp.version, color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyMedium)
@ -174,7 +172,6 @@ fun InstalledAppInfoScreen(
supportingContent = stringResource(viewModel.installedApp.installType.stringResource)
)
}
}
}
}

View File

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.WarningAmber
@ -24,6 +23,7 @@ import app.revanced.manager.data.room.apps.installed.InstalledApp
import app.revanced.manager.patcher.aapt.Aapt
import app.revanced.manager.ui.component.AppIcon
import app.revanced.manager.ui.component.AppLabel
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.LoadingIndicator
import app.revanced.manager.ui.component.NotificationCard
import app.revanced.manager.ui.viewmodel.InstalledAppsViewModel
@ -47,13 +47,12 @@ fun InstalledAppsScreen(
)
}
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = if (installedApps.isNullOrEmpty()) Arrangement.Center else Arrangement.Top
verticalArrangement = if (installedApps.isNullOrEmpty()) Arrangement.Center else Arrangement.Top,
) {
installedApps?.let { installedApps ->
if (installedApps.isNotEmpty()) {
items(
installedApps,

View File

@ -8,7 +8,6 @@ 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.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.pager.HorizontalPager
@ -62,6 +61,7 @@ import app.revanced.manager.domain.manager.PreferencesManager
import app.revanced.manager.patcher.patch.PatchInfo
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.Countdown
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.patches.OptionItem
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_SUPPORTED
@ -232,7 +232,10 @@ fun PatchesSelectorScreen(
}
) {
val bundle = bundles[pagerState.currentPage]
LazyColumn(modifier = Modifier.fillMaxSize()) {
LazyColumnWithScrollbar(
modifier = Modifier.fillMaxSize()
) {
fun List<PatchInfo>.searched() = filter {
it.name.contains(query, true)
}
@ -254,7 +257,7 @@ fun PatchesSelectorScreen(
)
}
if (!vm.allowExperimental) return@LazyColumn
if (!vm.allowExperimental) return@LazyColumnWithScrollbar
patchList(
uid = bundle.uid,
patches = bundle.unsupported.searched(),
@ -340,7 +343,7 @@ fun PatchesSelectorScreen(
pageContent = { index ->
val bundle = bundles[index]
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier.fillMaxSize()
) {
patchList(
@ -563,10 +566,10 @@ fun OptionsDialog(
)
}
) { paddingValues ->
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier.padding(paddingValues)
) {
if (patch.options == null) return@LazyColumn
if (patch.options == null) return@LazyColumnWithScrollbar
items(patch.options, key = { it.key }) { option ->
val key = option.key

View File

@ -8,11 +8,8 @@ import android.os.PowerManager
import android.provider.Settings
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
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.BatteryAlert
import androidx.compose.material.icons.outlined.*
@ -27,6 +24,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.NotificationCard
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.destination.SettingsDestination
@ -157,11 +155,10 @@ fun SettingsScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
AnimatedVisibility(visible = showBatteryButton) {
NotificationCard(

View File

@ -6,8 +6,6 @@ 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.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.ExperimentalMaterial3Api
@ -34,6 +32,7 @@ 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.LoadingIndicator
import app.revanced.manager.ui.model.SelectedApp
@ -79,11 +78,10 @@ fun VersionSelectorScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize()
.verticalScroll(rememberScrollState()),
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
viewModel.installedApp?.let { (packageInfo, installedApp) ->

View File

@ -13,8 +13,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Code
import androidx.compose.material.icons.outlined.FavoriteBorder
@ -38,6 +36,7 @@ import androidx.compose.ui.unit.dp
import app.revanced.manager.BuildConfig
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.util.isDebuggable
import app.revanced.manager.util.openUrl
@ -103,11 +102,10 @@ fun AboutSettingsScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState()),
.padding(paddingValues),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {

View File

@ -7,8 +7,6 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
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.outlined.Http
import androidx.compose.material3.AlertDialog
@ -34,9 +32,10 @@ import androidx.core.content.getSystemService
import androidx.lifecycle.viewModelScope
import app.revanced.manager.R
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.settings.SettingsListItem
import app.revanced.manager.ui.component.settings.BooleanItem
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.AdvancedSettingsViewModel
import org.koin.androidx.compose.getViewModel
@ -64,11 +63,10 @@ fun AdvancedSettingsScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
) {
val apiUrl by vm.prefs.api.getAsState()
var showApiUrlDialog by rememberSaveable { mutableStateOf(false) }

View File

@ -3,11 +3,11 @@ package app.revanced.manager.ui.screen.settings
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.*
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
@ -29,6 +29,7 @@ import androidx.compose.ui.unit.times
import app.revanced.manager.R
import app.revanced.manager.network.dto.ReVancedContributor
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.LoadingIndicator
import app.revanced.manager.ui.viewmodel.ContributorViewModel
import coil.compose.AsyncImage
@ -49,7 +50,7 @@ fun ContributorScreen(
)
},
) { paddingValues ->
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier
.fillMaxHeight()
.padding(paddingValues)

View File

@ -1,11 +1,8 @@
package app.revanced.manager.ui.screen.settings
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
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.Delete
import androidx.compose.material3.Checkbox
@ -21,9 +18,10 @@ 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.ColumnWithScrollbar
import app.revanced.manager.ui.component.GroupHeader
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.component.settings.BooleanItem
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.DownloadsViewModel
import org.koin.androidx.compose.getViewModel
@ -52,11 +50,10 @@ fun DownloadsSettingsScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
) {
BooleanItem(
preference = prefs.preferSplits,

View File

@ -3,8 +3,6 @@ package app.revanced.manager.ui.screen.settings
import android.os.Build
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -18,12 +16,13 @@ import androidx.lifecycle.viewModelScope
import app.revanced.manager.R
import app.revanced.manager.domain.manager.PreferencesManager
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.settings.BooleanItem
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.theme.Theme
import app.revanced.manager.ui.viewmodel.SettingsViewModel
import org.koin.compose.koinInject
import app.revanced.manager.ui.component.settings.SettingsListItem
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -50,11 +49,10 @@ fun GeneralSettingsScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
) {
GroupHeader(stringResource(R.string.appearance))

View File

@ -11,8 +11,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
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.outlined.Key
import androidx.compose.material3.*
@ -31,15 +29,16 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewModelScope
import app.revanced.manager.R
import app.revanced.manager.ui.viewmodel.ImportExportViewModel
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.PasswordField
import app.revanced.manager.ui.component.bundle.BundleSelector
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.ImportExportViewModel
import app.revanced.manager.util.toast
import kotlinx.coroutines.launch
import org.koin.androidx.compose.getViewModel
import app.revanced.manager.ui.component.settings.SettingsListItem
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -102,11 +101,10 @@ fun ImportExportSettingsScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
) {
GroupHeader(stringResource(R.string.signing))
GroupItem(

View File

@ -1,6 +1,7 @@
package app.revanced.manager.ui.screen.settings
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -8,6 +9,7 @@ import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppScaffold
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.Scrollbar
import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer
import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults
@ -26,9 +28,12 @@ fun LicensesScreen(
}
) { paddingValues ->
Column(modifier = Modifier.padding(paddingValues)) {
val lazyListState = rememberLazyListState()
LibrariesContainer(
modifier = Modifier
.fillMaxSize(),
lazyListState = lazyListState,
colors = LibraryDefaults.libraryColors(
backgroundColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground,
@ -36,6 +41,7 @@ fun LicensesScreen(
badgeContentColor = MaterialTheme.colorScheme.onPrimary,
)
)
Scrollbar(lazyListState = lazyListState, modifier = Modifier.padding(paddingValues))
}
}
}

View File

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
@ -20,6 +19,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.LoadingIndicator
import app.revanced.manager.ui.component.settings.Changelog
import app.revanced.manager.ui.viewmodel.ChangelogsViewModel
@ -43,7 +43,7 @@ fun ChangelogsScreen(
)
}
) { paddingValues ->
LazyColumn(
LazyColumnWithScrollbar(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize(),

View File

@ -1,11 +1,8 @@
package app.revanced.manager.ui.screen.settings.update
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
@ -13,14 +10,13 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.domain.manager.PreferencesManager
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.settings.BooleanItem
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.UpdatesSettingsViewModel
import kotlinx.coroutines.launch
import org.koin.androidx.compose.getViewModel
import org.koin.compose.rememberKoinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -40,11 +36,10 @@ fun UpdatesSettingsScreen(
)
}
) { paddingValues ->
Column(
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
) {
SettingsListItem(
modifier = Modifier.clickable {

View File

@ -28,6 +28,7 @@ coil = "2.4.0"
app-icon-loader-coil = "1.5.0"
skrapeit = "1.2.2"
libsu = "5.2.0"
scrollbars = "1.0.4"
[libraries]
# AndroidX Core
@ -106,6 +107,9 @@ libsu-core = { group = "com.github.topjohnwu.libsu", name = "core", version.ref
libsu-service = { group = "com.github.topjohnwu.libsu", name = "service", version.ref = "libsu" }
libsu-nio = { group = "com.github.topjohnwu.libsu", name = "nio", version.ref = "libsu" }
# Scrollbars
scrollbars = { group = "com.github.GIGAMOLE", name = "ComposeScrollbars", version.ref = "scrollbars" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinGradlePlugin" }