Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/java/app/revanced/manager/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ private fun ReVancedManager(vm: MainViewModel) {

SelectedAppInfoScreen(
onBackClick = navController::popBackStackSafe,
onSettingsClick = navController::navigateSafe,
onPatchClick = {
it.lifecycleScope.launch {
navController.navigateComplex(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ class NetworkInfo(app: Application) {
private val connectivityManager = app.getSystemService<ConnectivityManager>()!!

private fun getCapabilities() = connectivityManager.activeNetwork?.let { connectivityManager.getNetworkCapabilities(it) }
fun isConnected() = connectivityManager.activeNetwork != null
fun isUnmetered() = getCapabilities()?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) ?: true
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ class DownloaderRepository(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) Api30ResourceImpl(File(apkPath))
else OldResourceImpl(resources)

val packageLabel = with(pm) { packageInfo.label() }

return DownloaderPackage(
classNames.map { className ->
val downloader = classLoader
Expand All @@ -176,6 +178,7 @@ class DownloaderRepository(

LoadedDownloader(
packageName,
packageLabel,
className,
resources.getString(downloader.name),
scopeImpl,
Expand All @@ -185,7 +188,7 @@ class DownloaderRepository(
classLoader,
resourceImpl,
packageInfo.packageName,
with(pm) { packageInfo.label() },
packageLabel,
packageInfo.versionName.orEmpty()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import app.revanced.manager.downloader.Scope

class LoadedDownloader(
val packageName: String,
val packageLabel: String,
val className: String,
val name: String,
val scopeImpl: Scope,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fun LazyColumnWithScrollbarEdgeShadow(
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
showScrollbar: Boolean = true,
edgeShadowHeight: Dp = 40.dp,
edgeShadowProximity: Dp = 80.dp,
content: LazyListScope.() -> Unit
Expand Down Expand Up @@ -126,7 +127,7 @@ fun LazyColumnWithScrollbarEdgeShadow(
)
}

if (state.canScrollForward || state.canScrollBackward) {
if (showScrollbar && (state.canScrollForward || state.canScrollBackward)) {
Scrollbar(state)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ object BannerScaffoldDefaults {

@Composable
fun colors(
sheetBackgroundColor: Color = MaterialTheme.colorScheme.surfaceContainerLow,
sheetBackgroundColor: Color = MaterialTheme.colorScheme.surface,
bannerContentColor: Color = MaterialTheme.colorScheme.onSurface,
) = BannerScaffoldColors(
sheetBackgroundColor = sheetBackgroundColor,
Expand All @@ -220,15 +220,15 @@ fun BannerScaffold(
actions: @Composable RowScope.() -> Unit = {},
colors: BannerScaffoldColors = BannerScaffoldDefaults.colors(),
scrollBehavior: BannerScrollBehavior? = null,
minCollapsedBannerSize: Dp = 96.dp,
bannerBackground: @Composable BannerScope.() -> Unit = {},
bannerContent: @Composable BannerScope.() -> Unit,
sheetContent: @Composable (PaddingValues) -> Unit,
) {
BoxWithConstraints(modifier.fillMaxSize()) {
val density = LocalDensity.current
val isLandscape = maxWidth > maxHeight
val axisFraction = if (isLandscape) 0.5f else 0.35f
val collapsedAxisFraction = if (isLandscape) axisFraction else 0.15f
val axisFraction = if (isLandscape) 0.5f else 0.25f

val topBarHeight = if (isLandscape) 0.dp else 64.dp
val topBarPx = with(density) { topBarHeight.roundToPx() }
Expand All @@ -238,9 +238,12 @@ fun BannerScaffold(
}
val availableMainAxisPx = (totalMainAxisPx - if (isLandscape) 0 else topBarPx).coerceAtLeast(0)
val expandedBannerPx = (availableMainAxisPx * axisFraction).roundToInt()
val collapsedBannerPx = (availableMainAxisPx * collapsedAxisFraction)
.roundToInt()
.coerceAtMost(expandedBannerPx)
val collapsedBannerPx = if (isLandscape) {
expandedBannerPx
} else {
with(density) { minCollapsedBannerSize.roundToPx() }
.coerceAtMost(expandedBannerPx)
}

val collapseFraction = if (isLandscape) 0f else scrollBehavior?.state?.collapsedFraction ?: 0f

Expand Down Expand Up @@ -290,7 +293,11 @@ fun BannerScaffold(
)

CompositionLocalProvider(LocalContentColor provides colors.bannerContentColor) {
Box(modifier = bannerBackgroundModifier) {
Box(
modifier = bannerBackgroundModifier
.clipToBounds()
.background(colors.sheetBackgroundColor)
) {
bannerScope.bannerBackground()
}
}
Expand Down Expand Up @@ -362,7 +369,7 @@ fun BannerScaffold(
modifier = Modifier
.align(Alignment.TopStart)
.then(if (isLandscape) Modifier.width(bannerSize) else Modifier.fillMaxWidth()),
title = { Text(title) },
title = { },
navigationIcon = {
if (onBackClick != null) {
TooltipIconButton(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package app.revanced.manager.ui.component.selectedapp

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.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.ListItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.network.downloader.LoadedDownloader
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.FullscreenDialog
import app.revanced.manager.ui.component.LoadingIndicator
import app.revanced.manager.ui.model.SelectedApp
import app.revanced.manager.util.enabled
import app.revanced.manager.util.transparentListItemColors

@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
@Composable
fun AppSourceSelectorDialog(
downloaders: Map<String, List<LoadedDownloader>>,
downloadedApps: List<SelectedApp.Local>,
activeSearchJob: LoadedDownloader?,
requiredVersion: String?,
autoSelection: SelectedApp,
onDismissRequest: () -> Unit,
onSelectAuto: () -> Unit,
onSelectDownloader: (LoadedDownloader) -> Unit,
onSelectFromStorage: () -> Unit,
onSelect: (SelectedApp) -> Unit,
) {
val canSelect = activeSearchJob == null

val hasDownloaded = downloadedApps.any {
requiredVersion == null || it.version == requiredVersion
}
val hasAutoSource =
downloaders.isNotEmpty() ||
hasDownloaded ||
autoSelection is SelectedApp.Installed

FullscreenDialog(onDismissRequest) {
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.app_source_dialog_title),
onBackClick = onDismissRequest
)
}
) { paddingValues ->
LazyColumn(Modifier.padding(paddingValues)) {
item("auto") {
ListItem(
modifier = Modifier
.clickable(
enabled = canSelect && hasAutoSource,
onClick = onSelectAuto
)
.enabled(hasAutoSource),
headlineContent = {
Text(stringResource(R.string.app_source_dialog_option_auto))
},
supportingContent = {
Text(
stringResource(
if (hasAutoSource)
R.string.app_source_dialog_option_auto_description
else
R.string.app_source_dialog_option_auto_unavailable
)
)
},
colors = transparentListItemColors
)
}

item("storage") {
ListItem(
modifier = Modifier.clickable(onClick = onSelectFromStorage),
headlineContent = { Text(stringResource(R.string.select_from_storage)) },
supportingContent = { Text(stringResource(R.string.select_from_storage_description)) },
colors = transparentListItemColors
)
}

if (downloadedApps.isNotEmpty()) {
item { HorizontalDivider() }

items(downloadedApps, key = { it.version }) { app ->
val usable =
requiredVersion == null || app.version == requiredVersion

ListItem(
modifier = Modifier
.clickable(enabled = canSelect && usable) { onSelect(app) }
.enabled(usable),
headlineContent = { Text(app.packageName) },
supportingContent = { Text(app.version) },
overlineContent = {
Text(stringResource(R.string.source_selector_category_downloaded))
},
colors = transparentListItemColors
)
}
}

if (downloaders.isNotEmpty()) {
item { HorizontalDivider() }

downloaders.forEach { (name, list) ->
items(list) { downloader ->
ListItem(
modifier = Modifier.clickable(enabled = canSelect) {
onSelectDownloader(downloader)
},
headlineContent = { Text(downloader.name) },
trailingContent = {
if (activeSearchJob == downloader) {
LoadingIndicator()
}
},
overlineContent = {
Text(name)
},
supportingContent = {
if (!requiredVersion.isNullOrEmpty()) Text("${autoSelection.packageName} ${autoSelection.version}")
},
colors = transparentListItemColors
)
}
}
}
}
}
}
}
Loading
Loading