Skip to content

Commit eb0811c

Browse files
committed
Merge branch 'improve-addremove-icons-in-splittunnelingscreen-droid-630'
2 parents b74f6d6 + 1946c16 commit eb0811c

File tree

6 files changed

+105
-83
lines changed

6 files changed

+105
-83
lines changed

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,14 @@ internal fun BaseCellTitle(
9393
title: String,
9494
style: TextStyle,
9595
modifier: Modifier = Modifier,
96+
color: Color = MaterialTheme.colorScheme.onPrimary,
9697
textAlign: TextAlign = TextAlign.Start
9798
) {
9899
Text(
99100
text = title,
100101
textAlign = textAlign,
101102
style = style,
102-
color = MaterialTheme.colorScheme.onPrimary,
103+
color = color,
103104
overflow = TextOverflow.Ellipsis,
104105
maxLines = 1,
105106
modifier = modifier
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package net.mullvad.mullvadvpn.compose.cell
2+
3+
import androidx.compose.material3.MaterialTheme
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.ui.Modifier
6+
import androidx.compose.ui.graphics.Color
7+
import androidx.compose.ui.text.TextStyle
8+
9+
@Composable
10+
fun HeaderCell(
11+
text: String,
12+
modifier: Modifier = Modifier,
13+
textStyle: TextStyle = MaterialTheme.typography.titleMedium,
14+
textColor: Color = MaterialTheme.colorScheme.onPrimary,
15+
background: Color = MaterialTheme.colorScheme.primary,
16+
) {
17+
BaseCell(
18+
title = {
19+
BaseCellTitle(
20+
title = text,
21+
style = textStyle,
22+
color = textColor,
23+
)
24+
},
25+
modifier = modifier,
26+
background = background,
27+
isRowEnabled = false
28+
)
29+
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SplitTunnelingCell.kt

+51-57
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,15 @@ package net.mullvad.mullvadvpn.compose.cell
33
import android.graphics.Bitmap
44
import androidx.compose.foundation.Image
55
import androidx.compose.foundation.background
6-
import androidx.compose.foundation.clickable
7-
import androidx.compose.foundation.layout.Column
8-
import androidx.compose.foundation.layout.Row
9-
import androidx.compose.foundation.layout.defaultMinSize
10-
import androidx.compose.foundation.layout.fillMaxWidth
116
import androidx.compose.foundation.layout.padding
127
import androidx.compose.foundation.layout.size
13-
import androidx.compose.foundation.layout.wrapContentHeight
148
import androidx.compose.material3.Icon
159
import androidx.compose.material3.MaterialTheme
1610
import androidx.compose.material3.Text
1711
import androidx.compose.runtime.*
1812
import androidx.compose.ui.Alignment
1913
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.graphics.Color
2015
import androidx.compose.ui.graphics.ImageBitmap
2116
import androidx.compose.ui.graphics.asImageBitmap
2217
import androidx.compose.ui.graphics.compositeOver
@@ -27,6 +22,7 @@ import androidx.compose.ui.unit.dp
2722
import kotlinx.coroutines.Dispatchers
2823
import kotlinx.coroutines.launch
2924
import net.mullvad.mullvadvpn.R
25+
import net.mullvad.mullvadvpn.compose.component.SpacedColumn
3026
import net.mullvad.mullvadvpn.lib.theme.AppTheme
3127
import net.mullvad.mullvadvpn.lib.theme.Dimens
3228
import net.mullvad.mullvadvpn.lib.theme.color.Alpha40
@@ -36,7 +32,7 @@ import net.mullvad.mullvadvpn.lib.theme.typeface.listItemText
3632
@Composable
3733
private fun PreviewTunnelingCell() {
3834
AppTheme {
39-
Column(
35+
SpacedColumn(
4036
modifier =
4137
Modifier.background(color = MaterialTheme.colorScheme.background).padding(20.dp)
4238
) {
@@ -52,6 +48,10 @@ fun SplitTunnelingCell(
5248
packageName: String?,
5349
isSelected: Boolean,
5450
modifier: Modifier = Modifier,
51+
backgroundColor: Color =
52+
MaterialTheme.colorScheme.primary
53+
.copy(alpha = Alpha40)
54+
.compositeOver(MaterialTheme.colorScheme.background),
5555
onResolveIcon: (String) -> Bitmap? = { null },
5656
onCellClicked: () -> Unit = {}
5757
) {
@@ -62,55 +62,49 @@ fun SplitTunnelingCell(
6262
icon = bitmap?.asImageBitmap()
6363
}
6464
}
65-
Row(
66-
modifier =
67-
modifier
68-
.wrapContentHeight()
69-
.defaultMinSize(minHeight = Dimens.listItemHeightExtra)
70-
.fillMaxWidth()
71-
.padding(bottom = Dimens.listItemDivider)
72-
.background(
73-
MaterialTheme.colorScheme.primary
65+
BaseCell(
66+
iconView = {
67+
Image(
68+
painter =
69+
icon?.let { iconImage -> BitmapPainter(iconImage) }
70+
?: painterResource(id = R.drawable.ic_icons_missing),
71+
contentDescription = null,
72+
modifier =
73+
Modifier.align(Alignment.CenterVertically).size(size = Dimens.listIconSize)
74+
)
75+
},
76+
title = {
77+
Text(
78+
text = title,
79+
style = MaterialTheme.typography.listItemText,
80+
color = MaterialTheme.colorScheme.onPrimary,
81+
modifier =
82+
Modifier.weight(1f)
83+
.padding(horizontal = Dimens.mediumPadding)
84+
.align(Alignment.CenterVertically)
85+
)
86+
},
87+
bodyView = {
88+
Icon(
89+
painter =
90+
painterResource(
91+
id =
92+
if (isSelected) {
93+
R.drawable.ic_icons_remove
94+
} else {
95+
R.drawable.ic_icons_add
96+
}
97+
),
98+
contentDescription = null,
99+
tint =
100+
MaterialTheme.colorScheme.onBackground
74101
.copy(alpha = Alpha40)
75-
.compositeOver(MaterialTheme.colorScheme.background)
76-
)
77-
.clickable(onClick = onCellClicked)
78-
) {
79-
Image(
80-
painter =
81-
icon?.let { iconImage -> BitmapPainter(iconImage) }
82-
?: painterResource(id = R.drawable.ic_icons_missing),
83-
contentDescription = null,
84-
modifier =
85-
Modifier.padding(start = Dimens.cellStartPadding)
86-
.align(Alignment.CenterVertically)
87-
.size(width = Dimens.listIconSize, height = Dimens.listIconSize)
88-
)
89-
Text(
90-
text = title,
91-
style = MaterialTheme.typography.listItemText,
92-
color = MaterialTheme.colorScheme.onPrimary,
93-
modifier =
94-
Modifier.weight(1f)
95-
.padding(horizontal = Dimens.mediumPadding, vertical = Dimens.smallPadding)
96-
.align(Alignment.CenterVertically)
97-
)
98-
Icon(
99-
painter =
100-
painterResource(
101-
id =
102-
if (isSelected) {
103-
R.drawable.ic_icons_remove
104-
} else {
105-
R.drawable.ic_icons_add
106-
}
107-
),
108-
contentDescription = null,
109-
tint = MaterialTheme.colorScheme.onBackground.copy(alpha = Alpha40),
110-
modifier =
111-
Modifier.padding(end = Dimens.cellStartPadding)
112-
.align(Alignment.CenterVertically)
113-
.padding(horizontal = Dimens.loadingSpinnerPadding)
114-
)
115-
}
102+
.compositeOver(backgroundColor),
103+
modifier = Modifier.size(size = Dimens.addIconSize)
104+
)
105+
},
106+
onCellClicked = onCellClicked,
107+
background = backgroundColor,
108+
modifier = modifier
109+
)
116110
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/LazyListExtensions.kt

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package net.mullvad.mullvadvpn.compose.extensions
22

33
import androidx.compose.foundation.lazy.LazyItemScope
44
import androidx.compose.foundation.lazy.LazyListScope
5+
import androidx.compose.foundation.lazy.itemsIndexed
56
import androidx.compose.material3.Divider
67
import androidx.compose.runtime.Composable
78

@@ -14,3 +15,14 @@ inline fun LazyListScope.itemWithDivider(
1415
itemContent()
1516
Divider()
1617
}
18+
19+
inline fun <T> LazyListScope.itemsIndexedWithDivider(
20+
items: List<T>,
21+
noinline key: ((index: Int, item: T) -> Any)? = null,
22+
crossinline contentType: (index: Int, item: T) -> Any? = { _, _ -> null },
23+
crossinline itemContent: @Composable LazyItemScope.(index: Int, item: T) -> Unit
24+
) =
25+
itemsIndexed(items = items, key = key, contentType = contentType) { index, item ->
26+
itemContent(index, item)
27+
Divider()
28+
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt

+9-22
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
99
import androidx.compose.foundation.layout.height
1010
import androidx.compose.foundation.layout.padding
1111
import androidx.compose.foundation.lazy.LazyColumn
12-
import androidx.compose.foundation.lazy.itemsIndexed
1312
import androidx.compose.material3.MaterialTheme
1413
import androidx.compose.material3.Text
1514
import androidx.compose.runtime.Composable
@@ -27,7 +26,7 @@ import com.ramcosta.composedestinations.annotation.Destination
2726
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
2827
import net.mullvad.mullvadvpn.R
2928
import net.mullvad.mullvadvpn.applist.AppData
30-
import net.mullvad.mullvadvpn.compose.cell.BaseCell
29+
import net.mullvad.mullvadvpn.compose.cell.HeaderCell
3130
import net.mullvad.mullvadvpn.compose.cell.HeaderSwitchComposeCell
3231
import net.mullvad.mullvadvpn.compose.cell.SplitTunnelingCell
3332
import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorLarge
@@ -37,6 +36,7 @@ import net.mullvad.mullvadvpn.compose.constant.CommonContentKey
3736
import net.mullvad.mullvadvpn.compose.constant.ContentType
3837
import net.mullvad.mullvadvpn.compose.constant.SplitTunnelingContentKey
3938
import net.mullvad.mullvadvpn.compose.extensions.itemWithDivider
39+
import net.mullvad.mullvadvpn.compose.extensions.itemsIndexedWithDivider
4040
import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState
4141
import net.mullvad.mullvadvpn.compose.transitions.SlideInFromRightTransition
4242
import net.mullvad.mullvadvpn.lib.theme.AppTheme
@@ -146,19 +146,13 @@ fun SplitTunnelingScreen(
146146
key = SplitTunnelingContentKey.EXCLUDED_APPLICATIONS,
147147
contentType = ContentType.HEADER
148148
) {
149-
BaseCell(
150-
title = {
151-
Text(
152-
text = stringResource(id = R.string.exclude_applications),
153-
style = MaterialTheme.typography.titleMedium,
154-
color = MaterialTheme.colorScheme.onPrimary
155-
)
156-
},
157-
bodyView = {},
149+
HeaderCell(
150+
modifier = Modifier.animateItemPlacement(),
151+
text = stringResource(id = R.string.exclude_applications),
158152
background = MaterialTheme.colorScheme.primary,
159153
)
160154
}
161-
itemsIndexed(
155+
itemsIndexedWithDivider(
162156
items = uiState.excludedApps,
163157
key = { _, listItem -> listItem.packageName },
164158
contentType = { _, _ -> ContentType.ITEM }
@@ -204,20 +198,13 @@ fun SplitTunnelingScreen(
204198
key = SplitTunnelingContentKey.INCLUDED_APPLICATIONS,
205199
contentType = ContentType.HEADER
206200
) {
207-
BaseCell(
201+
HeaderCell(
208202
modifier = Modifier.animateItemPlacement(),
209-
title = {
210-
Text(
211-
text = stringResource(id = R.string.all_applications),
212-
style = MaterialTheme.typography.titleMedium,
213-
color = MaterialTheme.colorScheme.onPrimary
214-
)
215-
},
216-
bodyView = {},
203+
text = stringResource(id = R.string.all_applications),
217204
background = MaterialTheme.colorScheme.primary,
218205
)
219206
}
220-
itemsIndexed(
207+
itemsIndexedWithDivider(
221208
items = uiState.includedApps,
222209
key = { _, listItem -> listItem.packageName },
223210
contentType = { _, _ -> ContentType.ITEM }

android/lib/theme/src/main/kotlin/net/mullvad/mullvadvpn/lib/theme/dimensions/Dimensions.kt

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import androidx.compose.ui.unit.dp
66
data class Dimensions(
77
val accountRowMinHeight: Dp = 48.dp,
88
val accountRowSpacing: Dp = 24.dp,
9+
val addIconSize: Dp = 24.dp,
910
val backButtonSideMargin: Dp = 30.dp,
1011
val bigIconSize: Dp = 44.dp,
1112
val buttonHeight: Dp = 44.dp,
1213
val buttonSpacing: Dp = 12.dp,
1314
val buttonVerticalPadding: Dp = 8.dp,
1415
val cellEndPadding: Dp = 16.dp,
1516
val cellFooterTopPadding: Dp = 6.dp,
16-
val cellHeight: Dp = 52.dp,
17+
val cellHeight: Dp = 56.dp,
1718
val cellLabelVerticalPadding: Dp = 14.dp,
1819
val cellStartPadding: Dp = 22.dp,
1920
val cellTopPadding: Dp = 6.dp,
@@ -43,8 +44,6 @@ data class Dimensions(
4344
val largePadding: Dp = 32.dp,
4445
val listIconSize: Dp = 24.dp,
4546
val listItemDivider: Dp = 1.dp,
46-
val listItemHeight: Dp = 50.dp,
47-
val listItemHeightExtra: Dp = 60.dp,
4847
val loadingSpinnerPadding: Dp = 12.dp,
4948
val loadingSpinnerSize: Dp = 24.dp,
5049
val loadingSpinnerSizeMedium: Dp = 28.dp,

0 commit comments

Comments
 (0)