Skip to content

Commit 19bddee

Browse files
Ushieplanshim
andcommitted
feat: Redesign SelectedAppInfoScreen
Co-authored-by: planshim <100317079+planshim@users.noreply.github.com>
1 parent 12b5127 commit 19bddee

9 files changed

Lines changed: 1381 additions & 1030 deletions

File tree

app/src/main/java/app/revanced/manager/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ private fun ReVancedManager(vm: MainViewModel) {
264264

265265
SelectedAppInfoScreen(
266266
onBackClick = navController::popBackStackSafe,
267+
onSettingsClick = navController::navigateSafe,
267268
onPatchClick = {
268269
it.lifecycleScope.launch {
269270
navController.navigateComplex(

app/src/main/java/app/revanced/manager/data/platform/NetworkInfo.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ class NetworkInfo(app: Application) {
99
private val connectivityManager = app.getSystemService<ConnectivityManager>()!!
1010

1111
private fun getCapabilities() = connectivityManager.activeNetwork?.let { connectivityManager.getNetworkCapabilities(it) }
12+
fun isConnected() = connectivityManager.activeNetwork != null
1213
fun isUnmetered() = getCapabilities()?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) ?: true
1314
}

app/src/main/java/app/revanced/manager/ui/component/LazyColumnWithScrollbarEdgeShadow.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fun LazyColumnWithScrollbarEdgeShadow(
3636
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
3737
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
3838
userScrollEnabled: Boolean = true,
39+
showScrollbar: Boolean = true,
3940
edgeShadowHeight: Dp = 40.dp,
4041
edgeShadowProximity: Dp = 80.dp,
4142
content: LazyListScope.() -> Unit
@@ -126,7 +127,7 @@ fun LazyColumnWithScrollbarEdgeShadow(
126127
)
127128
}
128129

129-
if (state.canScrollForward || state.canScrollBackward) {
130+
if (showScrollbar && (state.canScrollForward || state.canScrollBackward)) {
130131
Scrollbar(state)
131132
}
132133
}

app/src/main/java/app/revanced/manager/ui/component/scaffold/BannerScaffold.kt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ object BannerScaffoldDefaults {
194194

195195
@Composable
196196
fun colors(
197-
sheetBackgroundColor: Color = MaterialTheme.colorScheme.surfaceContainerLow,
197+
sheetBackgroundColor: Color = MaterialTheme.colorScheme.surface,
198198
bannerContentColor: Color = MaterialTheme.colorScheme.onSurface,
199199
) = BannerScaffoldColors(
200200
sheetBackgroundColor = sheetBackgroundColor,
@@ -220,15 +220,15 @@ fun BannerScaffold(
220220
actions: @Composable RowScope.() -> Unit = {},
221221
colors: BannerScaffoldColors = BannerScaffoldDefaults.colors(),
222222
scrollBehavior: BannerScrollBehavior? = null,
223+
minCollapsedBannerSize: Dp = 96.dp,
223224
bannerBackground: @Composable BannerScope.() -> Unit = {},
224225
bannerContent: @Composable BannerScope.() -> Unit,
225226
sheetContent: @Composable (PaddingValues) -> Unit,
226227
) {
227228
BoxWithConstraints(modifier.fillMaxSize()) {
228229
val density = LocalDensity.current
229230
val isLandscape = maxWidth > maxHeight
230-
val axisFraction = if (isLandscape) 0.5f else 0.35f
231-
val collapsedAxisFraction = if (isLandscape) axisFraction else 0.15f
231+
val axisFraction = if (isLandscape) 0.5f else 0.25f
232232

233233
val topBarHeight = if (isLandscape) 0.dp else 64.dp
234234
val topBarPx = with(density) { topBarHeight.roundToPx() }
@@ -238,9 +238,12 @@ fun BannerScaffold(
238238
}
239239
val availableMainAxisPx = (totalMainAxisPx - if (isLandscape) 0 else topBarPx).coerceAtLeast(0)
240240
val expandedBannerPx = (availableMainAxisPx * axisFraction).roundToInt()
241-
val collapsedBannerPx = (availableMainAxisPx * collapsedAxisFraction)
242-
.roundToInt()
243-
.coerceAtMost(expandedBannerPx)
241+
val collapsedBannerPx = if (isLandscape) {
242+
expandedBannerPx
243+
} else {
244+
with(density) { minCollapsedBannerSize.roundToPx() }
245+
.coerceAtMost(expandedBannerPx)
246+
}
244247

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

@@ -290,7 +293,11 @@ fun BannerScaffold(
290293
)
291294

292295
CompositionLocalProvider(LocalContentColor provides colors.bannerContentColor) {
293-
Box(modifier = bannerBackgroundModifier) {
296+
Box(
297+
modifier = bannerBackgroundModifier
298+
.clipToBounds()
299+
.background(colors.sheetBackgroundColor)
300+
) {
294301
bannerScope.bannerBackground()
295302
}
296303
}
@@ -362,7 +369,7 @@ fun BannerScaffold(
362369
modifier = Modifier
363370
.align(Alignment.TopStart)
364371
.then(if (isLandscape) Modifier.width(bannerSize) else Modifier.fillMaxWidth()),
365-
title = { Text(title) },
372+
title = { },
366373
navigationIcon = {
367374
if (onBackClick != null) {
368375
TooltipIconButton(
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package app.revanced.manager.ui.component.selectedapp
2+
3+
import androidx.compose.foundation.clickable
4+
import androidx.compose.foundation.layout.padding
5+
import androidx.compose.foundation.lazy.LazyColumn
6+
import androidx.compose.foundation.lazy.items
7+
import androidx.compose.material3.ExperimentalMaterial3Api
8+
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
9+
import androidx.compose.material3.HorizontalDivider
10+
import androidx.compose.material3.ListItem
11+
import androidx.compose.material3.Scaffold
12+
import androidx.compose.material3.Text
13+
import androidx.compose.runtime.Composable
14+
import androidx.compose.ui.Modifier
15+
import androidx.compose.ui.res.stringResource
16+
import app.revanced.manager.R
17+
import app.revanced.manager.network.downloader.LoadedDownloader
18+
import app.revanced.manager.ui.component.AppTopBar
19+
import app.revanced.manager.ui.component.FullscreenDialog
20+
import app.revanced.manager.ui.component.LoadingIndicator
21+
import app.revanced.manager.ui.model.SelectedApp
22+
import app.revanced.manager.util.enabled
23+
import app.revanced.manager.util.transparentListItemColors
24+
25+
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
26+
@Composable
27+
fun AppSourceSelectorDialog(
28+
downloaders: Map<String, List<LoadedDownloader>>,
29+
downloadedApps: List<SelectedApp.Local>,
30+
activeSearchJob: LoadedDownloader?,
31+
requiredVersion: String?,
32+
autoSelection: SelectedApp,
33+
onDismissRequest: () -> Unit,
34+
onSelectAuto: () -> Unit,
35+
onSelectDownloader: (LoadedDownloader) -> Unit,
36+
onSelectFromStorage: () -> Unit,
37+
onSelect: (SelectedApp) -> Unit,
38+
) {
39+
val canSelect = activeSearchJob == null
40+
41+
val hasDownloaded = downloadedApps.any {
42+
requiredVersion == null || it.version == requiredVersion
43+
}
44+
val hasAutoSource =
45+
downloaders.isNotEmpty() ||
46+
hasDownloaded ||
47+
autoSelection is SelectedApp.Installed
48+
49+
FullscreenDialog(onDismissRequest) {
50+
Scaffold(
51+
topBar = {
52+
AppTopBar(
53+
title = stringResource(R.string.app_source_dialog_title),
54+
onBackClick = onDismissRequest
55+
)
56+
}
57+
) { paddingValues ->
58+
LazyColumn(Modifier.padding(paddingValues)) {
59+
item("auto") {
60+
ListItem(
61+
modifier = Modifier
62+
.clickable(
63+
enabled = canSelect && hasAutoSource,
64+
onClick = onSelectAuto
65+
)
66+
.enabled(hasAutoSource),
67+
headlineContent = {
68+
Text(stringResource(R.string.app_source_dialog_option_auto))
69+
},
70+
supportingContent = {
71+
Text(
72+
stringResource(
73+
if (hasAutoSource)
74+
R.string.app_source_dialog_option_auto_description
75+
else
76+
R.string.app_source_dialog_option_auto_unavailable
77+
)
78+
)
79+
},
80+
colors = transparentListItemColors
81+
)
82+
}
83+
84+
item("storage") {
85+
ListItem(
86+
modifier = Modifier.clickable(onClick = onSelectFromStorage),
87+
headlineContent = { Text(stringResource(R.string.select_from_storage)) },
88+
supportingContent = { Text(stringResource(R.string.select_from_storage_description)) },
89+
colors = transparentListItemColors
90+
)
91+
}
92+
93+
if (downloadedApps.isNotEmpty()) {
94+
item { HorizontalDivider() }
95+
96+
items(downloadedApps, key = { it.version }) { app ->
97+
val usable =
98+
requiredVersion == null || app.version == requiredVersion
99+
100+
ListItem(
101+
modifier = Modifier
102+
.clickable(enabled = canSelect && usable) { onSelect(app) }
103+
.enabled(usable),
104+
headlineContent = { Text(app.packageName) },
105+
supportingContent = { Text(app.version) },
106+
overlineContent = {
107+
Text(stringResource(R.string.source_selector_category_downloaded))
108+
},
109+
colors = transparentListItemColors
110+
)
111+
}
112+
}
113+
114+
if (downloaders.isNotEmpty()) {
115+
item { HorizontalDivider() }
116+
117+
downloaders.forEach { (name, list) ->
118+
items(list) { downloader ->
119+
ListItem(
120+
modifier = Modifier.clickable(enabled = canSelect) {
121+
onSelectDownloader(downloader)
122+
},
123+
headlineContent = { Text(downloader.name) },
124+
trailingContent = {
125+
if (activeSearchJob == downloader) {
126+
LoadingIndicator()
127+
}
128+
},
129+
overlineContent = {
130+
Text(name)
131+
},
132+
supportingContent = {
133+
if (!requiredVersion.isNullOrEmpty()) Text("${autoSelection.packageName} ${autoSelection.version}")
134+
},
135+
colors = transparentListItemColors
136+
)
137+
}
138+
}
139+
}
140+
}
141+
}
142+
}
143+
}

0 commit comments

Comments
 (0)