Skip to content

Commit 72ad6dd

Browse files
authored
fix: Overall improvement of the UI, code, and documentation (#3073)
2 parents f6ea379 + 0586e76 commit 72ad6dd

68 files changed

Lines changed: 1464 additions & 831 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/build.gradle.kts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,6 @@ android {
237237
generateLocaleConfig = true
238238
}
239239

240-
android {
241-
lint {
242-
disable.add("ExtraTranslation")
243-
}
244-
}
245-
246240
externalNativeBuild {
247241
cmake {
248242
path = file("src/main/cpp/CMakeLists.txt")

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

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,80 @@ package app.revanced.manager.ui.component
22

33
import android.content.pm.PackageInfo
44
import androidx.compose.foundation.Image
5-
import androidx.compose.foundation.shape.RoundedCornerShape
5+
import androidx.compose.foundation.layout.Box
66
import androidx.compose.material.icons.Icons
77
import androidx.compose.material.icons.filled.Android
88
import androidx.compose.material3.LocalContentColor
9-
import androidx.compose.material3.MaterialTheme
109
import androidx.compose.runtime.Composable
10+
import androidx.compose.runtime.LaunchedEffect
1111
import androidx.compose.runtime.getValue
1212
import androidx.compose.runtime.mutableStateOf
13-
import androidx.compose.runtime.saveable.rememberSaveable
13+
import androidx.compose.runtime.remember
1414
import androidx.compose.runtime.setValue
15+
import androidx.compose.ui.Alignment
1516
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.draw.alpha
1618
import androidx.compose.ui.graphics.ColorFilter
1719
import androidx.compose.ui.graphics.vector.rememberVectorPainter
20+
import androidx.compose.ui.platform.LocalContext
1821
import coil.compose.AsyncImage
19-
import com.eygraber.compose.placeholder.material3.placeholder
22+
import coil.request.ImageRequest
23+
import kotlinx.coroutines.yield
2024

2125
@Composable
2226
fun AppIcon(
2327
packageInfo: PackageInfo?,
2428
contentDescription: String?,
2529
modifier: Modifier = Modifier
2630
) {
27-
var showPlaceHolder by rememberSaveable { mutableStateOf(true) }
31+
val context = LocalContext.current
32+
val placeholderPainter = rememberVectorPainter(Icons.Default.Android)
33+
val placeholderColorFilter = ColorFilter.tint(LocalContentColor.current)
2834

2935
if (packageInfo == null) {
30-
val image = rememberVectorPainter(Icons.Default.Android)
31-
val colorFilter = ColorFilter.tint(LocalContentColor.current)
32-
3336
Image(
34-
image,
35-
contentDescription,
36-
modifier,
37-
colorFilter = colorFilter
37+
painter = placeholderPainter,
38+
contentDescription = contentDescription,
39+
modifier = modifier,
40+
colorFilter = placeholderColorFilter
3841
)
3942
} else {
40-
AsyncImage(
41-
packageInfo,
42-
contentDescription,
43-
Modifier.placeholder(visible = showPlaceHolder, color = MaterialTheme.colorScheme.inverseOnSurface, shape = RoundedCornerShape(100)).then(modifier),
44-
onSuccess = { showPlaceHolder = false }
45-
)
43+
var showPlaceHolder by remember(packageInfo.packageName) { mutableStateOf(true) }
44+
var shouldLoadIcon by remember(packageInfo.packageName) { mutableStateOf(false) }
45+
46+
val request = remember(context, packageInfo.packageName) {
47+
ImageRequest.Builder(context)
48+
.data(packageInfo)
49+
// .memoryCachePolicy(CachePolicy.DISABLED)
50+
.build()
51+
}
52+
53+
LaunchedEffect(packageInfo.packageName) {
54+
yield()
55+
shouldLoadIcon = true
56+
}
57+
58+
Box(
59+
modifier = modifier,
60+
contentAlignment = Alignment.Center
61+
) {
62+
if (shouldLoadIcon) {
63+
AsyncImage(
64+
model = request,
65+
contentDescription = contentDescription,
66+
modifier = Modifier.alpha(if (showPlaceHolder) 0f else 1f),
67+
onSuccess = { showPlaceHolder = false },
68+
onError = { showPlaceHolder = true }
69+
)
70+
}
71+
72+
if (showPlaceHolder) {
73+
Image(
74+
painter = placeholderPainter,
75+
contentDescription = contentDescription,
76+
colorFilter = placeholderColorFilter
77+
)
78+
}
79+
}
4680
}
4781
}

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
77
import androidx.compose.material3.ExperimentalMaterial3Api
88
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
99
import androidx.compose.material3.Icon
10-
import androidx.compose.material3.IconButton
11-
import androidx.compose.material3.IconButtonDefaults
1210
import androidx.compose.material3.MaterialTheme
1311
import androidx.compose.material3.Scaffold
1412
import androidx.compose.material3.Text
@@ -71,7 +69,10 @@ fun AppTopBar(
7169
scrollBehavior = scrollBehavior,
7270
navigationIcon = {
7371
if (onBackClick != null) {
74-
IconButton(onClick = onBackClick, shapes = IconButtonDefaults.shapes()) {
72+
TooltipIconButton(
73+
onClick = onBackClick,
74+
tooltip = stringResource(R.string.back),
75+
) {
7576
backIcon()
7677
}
7778
}
@@ -110,7 +111,10 @@ fun AppTopBar(
110111
scrollBehavior = scrollBehavior,
111112
navigationIcon = {
112113
if (onBackClick != null) {
113-
IconButton(onClick = onBackClick, shapes = IconButtonDefaults.shapes()) {
114+
TooltipIconButton(
115+
onClick = onBackClick,
116+
tooltip = stringResource(R.string.back),
117+
) {
114118
backIcon()
115119
}
116120
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import androidx.compose.material.icons.Icons
55
import androidx.compose.material.icons.filled.KeyboardArrowUp
66
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
77
import androidx.compose.material3.Icon
8-
import androidx.compose.material3.IconButton
9-
import androidx.compose.material3.IconButtonDefaults
108
import androidx.compose.runtime.Composable
119
import androidx.compose.runtime.getValue
1210
import androidx.compose.ui.Modifier
@@ -30,10 +28,13 @@ fun ArrowButton(
3028
)
3129

3230
onClick?.let {
33-
IconButton(onClick = it, shapes = IconButtonDefaults.shapes()) {
31+
TooltipIconButton(
32+
onClick = it,
33+
tooltip = stringResource(description),
34+
) { contentDescription ->
3435
Icon(
3536
imageVector = Icons.Filled.KeyboardArrowUp,
36-
contentDescription = stringResource(description),
37+
contentDescription = contentDescription,
3738
modifier = Modifier
3839
.rotate(rotation)
3940
.then(modifier)

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import androidx.compose.material.icons.filled.Share
1010
import androidx.compose.material3.ExperimentalMaterial3Api
1111
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
1212
import androidx.compose.material3.Icon
13-
import androidx.compose.material3.IconButton
14-
import androidx.compose.material3.IconButtonDefaults
1513
import androidx.compose.material3.Scaffold
1614
import androidx.compose.material3.Text
1715
import androidx.compose.runtime.Composable
@@ -41,7 +39,7 @@ fun ExceptionViewerDialog(text: String, onDismiss: () -> Unit) {
4139
)
4240
},
4341
actions = {
44-
IconButton(
42+
TooltipIconButton(
4543
onClick = {
4644
val sendIntent: Intent = Intent().apply {
4745
action = Intent.ACTION_SEND
@@ -55,7 +53,7 @@ fun ExceptionViewerDialog(text: String, onDismiss: () -> Unit) {
5553
val shareIntent = Intent.createChooser(sendIntent, null)
5654
context.startActivity(shareIntent)
5755
},
58-
shapes = IconButtonDefaults.shapes(),
56+
tooltip = stringResource(R.string.share)
5957
) {
6058
Icon(
6159
Icons.Filled.Share,

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

Lines changed: 35 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ import androidx.compose.material3.Card
1515
import androidx.compose.material3.CardDefaults
1616
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
1717
import androidx.compose.material3.Icon
18-
import androidx.compose.material3.IconButton
19-
import androidx.compose.material3.IconButtonDefaults
2018
import androidx.compose.material3.MaterialTheme
2119
import androidx.compose.material3.Text
2220
import androidx.compose.runtime.Composable
@@ -28,59 +26,8 @@ import androidx.compose.ui.res.stringResource
2826
import androidx.compose.ui.unit.dp
2927
import app.revanced.manager.R
3028

31-
@Composable
32-
fun NotificationCard(
33-
text: String,
34-
icon: ImageVector,
35-
modifier: Modifier = Modifier,
36-
actions: (@Composable RowScope.() -> Unit)? = null,
37-
title: String? = null,
38-
isWarning: Boolean = false
39-
) {
40-
val color =
41-
if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer
42-
43-
NotificationCardInstance(modifier = modifier, isWarning = isWarning) {
44-
Row(
45-
modifier = Modifier.padding(16.dp),
46-
horizontalArrangement = Arrangement.spacedBy(16.dp)
47-
) {
48-
Box(
49-
modifier = Modifier.size(28.dp),
50-
contentAlignment = Alignment.Center
51-
) {
52-
Icon(
53-
modifier = Modifier.size(24.dp),
54-
imageVector = icon,
55-
contentDescription = null,
56-
tint = color,
57-
)
58-
}
59-
60-
Column(
61-
verticalArrangement = Arrangement.spacedBy(8.dp)
62-
) {
63-
title?.let {
64-
Text(
65-
text = it,
66-
style = MaterialTheme.typography.titleLarge,
67-
color = color,
68-
)
69-
}
70-
Text(
71-
text = text,
72-
style = MaterialTheme.typography.bodyMedium,
73-
color = color,
74-
)
75-
Row(
76-
horizontalArrangement = Arrangement.End,
77-
modifier = Modifier.fillMaxWidth()
78-
) {
79-
actions?.invoke(this)
80-
}
81-
}
82-
}
83-
}
29+
enum class NotificationCardType {
30+
NORMAL, WARNING, ERROR
8431
}
8532

8633
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@@ -89,20 +36,25 @@ fun NotificationCard(
8936
text: String,
9037
icon: ImageVector,
9138
modifier: Modifier = Modifier,
39+
actions: (@Composable RowScope.() -> Unit)? = null,
9240
title: String? = null,
93-
isWarning: Boolean = false,
41+
type: NotificationCardType = NotificationCardType.NORMAL,
9442
onDismiss: (() -> Unit)? = null,
9543
onClick: (() -> Unit)? = null
9644
) {
9745
val color =
98-
if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer
46+
when (type) {
47+
NotificationCardType.ERROR -> MaterialTheme.colorScheme.onError
48+
NotificationCardType.WARNING -> MaterialTheme.colorScheme.onPrimaryContainer
49+
else -> MaterialTheme.colorScheme.onTertiaryContainer
50+
}
9951

100-
NotificationCardInstance(modifier = modifier, isWarning = isWarning, onClick = onClick) {
52+
NotificationCardInstance(modifier = modifier, type = type, onClick = onClick) {
10153
Row(
10254
modifier = Modifier
10355
.fillMaxWidth()
10456
.padding(16.dp),
105-
verticalAlignment = Alignment.CenterVertically,
57+
verticalAlignment = Alignment.Top,
10658
horizontalArrangement = Arrangement.spacedBy(16.dp),
10759
) {
10860
Box(
@@ -116,34 +68,34 @@ fun NotificationCard(
11668
tint = color,
11769
)
11870
}
119-
if (title != null) {
120-
Column(
121-
modifier = Modifier.weight(1f),
122-
verticalArrangement = Arrangement.spacedBy(6.dp)
123-
) {
124-
Text(
125-
text = title,
126-
style = MaterialTheme.typography.titleLarge,
127-
color = color,
128-
)
71+
Column(
72+
modifier = Modifier.weight(1f),
73+
verticalArrangement = Arrangement.spacedBy(8.dp)
74+
) {
75+
title?.let {
12976
Text(
130-
text = text,
131-
style = MaterialTheme.typography.bodyMedium,
77+
text = it,
78+
style = MaterialTheme.typography.bodyLarge,
13279
color = color,
13380
)
13481
}
135-
} else {
13682
Text(
137-
modifier = Modifier.weight(1f),
13883
text = text,
13984
style = MaterialTheme.typography.bodyMedium,
14085
color = color,
14186
)
87+
actions?.let {
88+
Row(
89+
modifier = Modifier.fillMaxWidth(),
90+
horizontalArrangement = Arrangement.End,
91+
content = it
92+
)
93+
}
14294
}
14395
if (onDismiss != null) {
144-
IconButton(
96+
TooltipIconButton(
14597
onClick = onDismiss,
146-
shapes = IconButtonDefaults.shapes(),
98+
tooltip = stringResource(R.string.close),
14799
) {
148100
Icon(
149101
imageVector = Icons.Outlined.Close,
@@ -159,12 +111,18 @@ fun NotificationCard(
159111
@Composable
160112
private fun NotificationCardInstance(
161113
modifier: Modifier = Modifier,
162-
isWarning: Boolean = false,
114+
type: NotificationCardType = NotificationCardType.NORMAL,
163115
onClick: (() -> Unit)? = null,
164116
content: @Composable () -> Unit,
165117
) {
166118
val colors =
167-
CardDefaults.cardColors(containerColor = if (isWarning) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primaryContainer)
119+
CardDefaults.cardColors(
120+
containerColor = when (type) {
121+
NotificationCardType.ERROR -> MaterialTheme.colorScheme.error
122+
NotificationCardType.WARNING -> MaterialTheme.colorScheme.primaryContainer
123+
else -> MaterialTheme.colorScheme.tertiaryContainer
124+
}
125+
)
168126
val defaultModifier = Modifier
169127
.fillMaxWidth()
170128
.clip(RoundedCornerShape(24.dp))

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import androidx.compose.material.icons.outlined.Visibility
66
import androidx.compose.material.icons.outlined.VisibilityOff
77
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
88
import androidx.compose.material3.Icon
9-
import androidx.compose.material3.IconButton
10-
import androidx.compose.material3.IconButtonDefaults
119
import androidx.compose.material3.OutlinedTextField
1210
import androidx.compose.runtime.Composable
1311
import androidx.compose.runtime.getValue
@@ -36,12 +34,13 @@ fun PasswordField(modifier: Modifier = Modifier, value: String, onValueChange: (
3634
label = label,
3735
modifier = modifier,
3836
trailingIcon = {
39-
IconButton(onClick = {
40-
visible = !visible
41-
}, shapes = IconButtonDefaults.shapes()) {
42-
val (icon, description) = remember(visible) {
43-
if (visible) Icons.Outlined.VisibilityOff to R.string.hide_password_field else Icons.Outlined.Visibility to R.string.show_password_field
44-
}
37+
val (icon, description) = remember(visible) {
38+
if (visible) Icons.Outlined.VisibilityOff to R.string.hide_password_field else Icons.Outlined.Visibility to R.string.show_password_field
39+
}
40+
TooltipIconButton(
41+
onClick = { visible = !visible },
42+
tooltip = stringResource(description)
43+
) {
4544
Icon(icon, stringResource(description))
4645
}
4746
},

0 commit comments

Comments
 (0)