@@ -32,12 +32,14 @@ import net.mullvad.mullvadvpn.compose.cell.BaseCell
32
32
import net.mullvad.mullvadvpn.compose.cell.HeaderSwitchComposeCell
33
33
import net.mullvad.mullvadvpn.compose.cell.SplitTunnelingCell
34
34
import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorLarge
35
+ import net.mullvad.mullvadvpn.compose.component.MullvadSwitch
35
36
import net.mullvad.mullvadvpn.compose.component.NavigateBackIconButton
36
- import net.mullvad.mullvadvpn.compose.component.ScaffoldWithMediumTopBar
37
+ import net.mullvad.mullvadvpn.compose.component.ScaffoldWithLargeTopBarAndToggleButton
37
38
import net.mullvad.mullvadvpn.compose.constant.CommonContentKey
38
39
import net.mullvad.mullvadvpn.compose.constant.ContentType
39
40
import net.mullvad.mullvadvpn.compose.constant.SplitTunnelingContentKey
40
41
import net.mullvad.mullvadvpn.compose.extensions.itemWithDivider
42
+ import net.mullvad.mullvadvpn.compose.state.AppListState
41
43
import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState
42
44
import net.mullvad.mullvadvpn.compose.transitions.SlideInFromRightTransition
43
45
import net.mullvad.mullvadvpn.lib.theme.AppTheme
@@ -51,29 +53,32 @@ private fun PreviewSplitTunnelingScreen() {
51
53
AppTheme {
52
54
SplitTunnelingScreen (
53
55
uiState =
54
- SplitTunnelingUiState .ShowAppList (
55
- excludedApps =
56
- listOf (
57
- AppData (
58
- packageName = " my.package.a" ,
59
- name = " TitleA" ,
60
- iconRes = R .drawable.icon_alert,
61
- ),
62
- AppData (
63
- packageName = " my.package.b" ,
64
- name = " TitleB" ,
65
- iconRes = R .drawable.icon_chevron,
66
- )
67
- ),
68
- includedApps =
69
- listOf (
70
- AppData (
71
- packageName = " my.package.c" ,
72
- name = " TitleC" ,
73
- iconRes = R .drawable.icon_alert
74
- )
75
- ),
76
- showSystemApps = true
56
+ SplitTunnelingUiState (
57
+ appListState =
58
+ AppListState .ShowAppList (
59
+ excludedApps =
60
+ listOf (
61
+ AppData (
62
+ packageName = " my.package.a" ,
63
+ name = " TitleA" ,
64
+ iconRes = R .drawable.icon_alert
65
+ ),
66
+ AppData (
67
+ packageName = " my.package.b" ,
68
+ name = " TitleB" ,
69
+ iconRes = R .drawable.icon_chevron
70
+ )
71
+ ),
72
+ includedApps =
73
+ listOf (
74
+ AppData (
75
+ packageName = " my.package.c" ,
76
+ name = " TitleC" ,
77
+ iconRes = R .drawable.icon_alert
78
+ )
79
+ ),
80
+ showSystemApps = true
81
+ )
77
82
)
78
83
)
79
84
}
@@ -88,6 +93,7 @@ fun SplitTunneling(navigator: DestinationsNavigator) {
88
93
val packageManager = remember(context) { context.packageManager }
89
94
SplitTunnelingScreen (
90
95
uiState = state,
96
+ onShowSplitTunneling = viewModel::enableSplitTunneling,
91
97
onShowSystemAppsClick = viewModel::onShowSystemAppsClick,
92
98
onExcludeAppClick = viewModel::onExcludeAppClick,
93
99
onIncludeAppClick = viewModel::onIncludeAppClick,
@@ -101,18 +107,25 @@ fun SplitTunneling(navigator: DestinationsNavigator) {
101
107
@Composable
102
108
@OptIn(ExperimentalFoundationApi ::class )
103
109
fun SplitTunnelingScreen (
104
- uiState : SplitTunnelingUiState = SplitTunnelingUiState .Loading ,
110
+ uiState : SplitTunnelingUiState = SplitTunnelingUiState (),
111
+ onShowSplitTunneling : (Boolean ) -> Unit = {},
105
112
onShowSystemAppsClick : (show: Boolean ) -> Unit = {},
106
113
onExcludeAppClick : (packageName: String ) -> Unit = {},
107
114
onIncludeAppClick : (packageName: String ) -> Unit = {},
108
115
onBackClick : () -> Unit = {},
109
- onResolveIcon : (String ) -> Bitmap ? = { null },
116
+ onResolveIcon : (String ) -> Bitmap ? = { null }
110
117
) {
111
118
val focusManager = LocalFocusManager .current
112
119
113
- ScaffoldWithMediumTopBar (
120
+ ScaffoldWithLargeTopBarAndToggleButton (
114
121
modifier = Modifier .fillMaxSize(),
115
122
appBarTitle = stringResource(id = R .string.split_tunneling),
123
+ switch = {
124
+ MullvadSwitch (
125
+ checked = uiState.checked,
126
+ onCheckedChange = { newValue -> onShowSplitTunneling(newValue) }
127
+ )
128
+ },
116
129
navigationIcon = { NavigateBackIconButton (onBackClick) }
117
130
) { modifier, lazyListState ->
118
131
LazyColumn (
@@ -134,14 +147,14 @@ fun SplitTunnelingScreen(
134
147
)
135
148
}
136
149
}
137
- when (uiState) {
138
- SplitTunnelingUiState .Loading -> {
150
+ when (val appList = uiState.appListState ) {
151
+ AppListState .Loading -> {
139
152
item(key = CommonContentKey .PROGRESS , contentType = ContentType .PROGRESS ) {
140
153
MullvadCircularProgressIndicatorLarge ()
141
154
}
142
155
}
143
- is SplitTunnelingUiState .ShowAppList -> {
144
- if (uiState .excludedApps.isNotEmpty()) {
156
+ is AppListState .ShowAppList -> {
157
+ if (appList .excludedApps.isNotEmpty()) {
145
158
itemWithDivider(
146
159
key = SplitTunnelingContentKey .EXCLUDED_APPLICATIONS ,
147
160
contentType = ContentType .HEADER
@@ -155,11 +168,11 @@ fun SplitTunnelingScreen(
155
168
)
156
169
},
157
170
bodyView = {},
158
- background = MaterialTheme .colorScheme.primary,
171
+ background = MaterialTheme .colorScheme.primary
159
172
)
160
173
}
161
174
itemsIndexed(
162
- items = uiState .excludedApps,
175
+ items = appList .excludedApps,
163
176
key = { _, listItem -> listItem.packageName },
164
177
contentType = { _, _ -> ContentType .ITEM }
165
178
) { index, listItem ->
@@ -172,7 +185,7 @@ fun SplitTunnelingScreen(
172
185
) {
173
186
// Move focus down unless the clicked item was the last in this
174
187
// section.
175
- if (index < uiState .excludedApps.size - 1 ) {
188
+ if (index < appList .excludedApps.size - 1 ) {
176
189
focusManager.moveFocus(FocusDirection .Down )
177
190
} else {
178
191
focusManager.moveFocus(FocusDirection .Up )
@@ -195,7 +208,7 @@ fun SplitTunnelingScreen(
195
208
) {
196
209
HeaderSwitchComposeCell (
197
210
title = stringResource(id = R .string.show_system_apps),
198
- isToggled = uiState .showSystemApps,
211
+ isToggled = appList .showSystemApps,
199
212
onCellClicked = { newValue -> onShowSystemAppsClick(newValue) },
200
213
modifier = Modifier .animateItemPlacement()
201
214
)
@@ -214,11 +227,11 @@ fun SplitTunnelingScreen(
214
227
)
215
228
},
216
229
bodyView = {},
217
- background = MaterialTheme .colorScheme.primary,
230
+ background = MaterialTheme .colorScheme.primary
218
231
)
219
232
}
220
233
itemsIndexed(
221
- items = uiState .includedApps,
234
+ items = appList .includedApps,
222
235
key = { _, listItem -> listItem.packageName },
223
236
contentType = { _, _ -> ContentType .ITEM }
224
237
) { index, listItem ->
@@ -231,7 +244,7 @@ fun SplitTunnelingScreen(
231
244
) {
232
245
// Move focus down unless the clicked item was the last in this
233
246
// section.
234
- if (index < uiState .includedApps.size - 1 ) {
247
+ if (index < appList .includedApps.size - 1 ) {
235
248
focusManager.moveFocus(FocusDirection .Down )
236
249
} else {
237
250
focusManager.moveFocus(FocusDirection .Up )
@@ -241,6 +254,7 @@ fun SplitTunnelingScreen(
241
254
}
242
255
}
243
256
}
257
+ AppListState .Disabled -> {}
244
258
}
245
259
}
246
260
}
0 commit comments