Skip to content

Commit 17788c6

Browse files
committed
Merge branch 'add-android-daita-droid-1192'
2 parents b0b7db0 + fca422d commit 17788c6

File tree

75 files changed

+616
-126
lines changed

Some content is hidden

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

75 files changed

+616
-126
lines changed

.github/workflows/android-app.yml

+10
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ jobs:
175175
with:
176176
submodules: true
177177

178+
- name: Checkout wireguard-go-rs recursively
179+
run: |
180+
git config --global --add safe.directory '*'
181+
git submodule update --init --recursive --depth=1 wireguard-go-rs
182+
178183
- name: Calculate native lib cache hash
179184
id: native-lib-cache-hash
180185
shell: bash
@@ -201,6 +206,8 @@ jobs:
201206
RUSTFLAGS: --deny warnings
202207
BUILD_TYPE: debug
203208
run: |
209+
# Temporary fix to address maybenot.h build issues.
210+
cargo install --force cbindgen --version "0.26.0"
204211
ARCHITECTURES="${{ matrix.abi }}"
205212
UNSTRIPPED_LIB_PATH="$CARGO_TARGET_DIR/${{ matrix.target }}/$BUILD_TYPE/libmullvad_jni.so"
206213
STRIPPED_LIB_PATH="./android/app/build/extraJni/${{ matrix.abi }}/libmullvad_jni.so"
@@ -319,6 +326,9 @@ jobs:
319326
name: relay-list
320327
path: android/app/build/extraAssets
321328

329+
- name: Copy maybenot machines to asset directory
330+
run: cp dist-assets/maybenot_machines android/app/build/extraAssets/maybenot_machines
331+
322332
- name: Build app
323333
uses: burrunan/gradle-cache-action@v1
324334
with:

.github/workflows/clippy.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
- name: Checkout wireguard-go submodule
9898
run: |
9999
git config --global --add safe.directory '*'
100-
git submodule update --init --depth=1 wireguard-go-rs
100+
git submodule update --init --recursive --depth=1 wireguard-go-rs
101101
102102
- name: Clippy check
103103
env:

.github/workflows/rust-unused-dependencies.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
- name: Checkout wireguard-go submodule
8080
run: |
8181
git config --global --add safe.directory '*'
82-
git submodule update --init --depth=1 wireguard-go-rs
82+
git submodule update --init --recursive --depth=1 wireguard-go-rs
8383
8484
- name: Install nightly Rust toolchain
8585
run: |

android/app/build.gradle.kts

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ plugins {
2020
val repoRootPath = rootProject.projectDir.absoluteFile.parentFile.absolutePath
2121
val extraAssetsDirectory = "${project.buildDir}/extraAssets"
2222
val relayListPath = "$extraAssetsDirectory/relays.json"
23+
val maybenotMachinesDirectory = "$extraAssetsDirectory/maybenot_machines"
2324
val defaultChangelogAssetsDirectory = "$repoRootPath/android/src/main/play/release-notes/"
2425
val extraJniDirectory = "${project.buildDir}/extraJni"
2526

@@ -239,6 +240,7 @@ android {
239240
// Ensure all relevant assemble tasks depend on our ensure tasks.
240241
tasks.get("assemble$capitalizedVariantName").apply {
241242
dependsOn(tasks.get("ensureRelayListExist"))
243+
dependsOn(tasks.get("ensureMaybenotMachinesExist"))
242244
dependsOn(tasks.get("ensureJniDirectoryExist"))
243245
dependsOn(tasks.get("ensureValidVersionCode"))
244246
}
@@ -283,6 +285,14 @@ tasks.register("ensureRelayListExist") {
283285
}
284286
}
285287

288+
tasks.register("ensureMaybenotMachinesExist") {
289+
doLast {
290+
if (!file(maybenotMachinesDirectory).exists()) {
291+
throw GradleException("Missing maybenot machines: $maybenotMachinesDirectory")
292+
}
293+
}
294+
}
295+
286296
tasks.register("ensureJniDirectoryExist") {
287297
doLast {
288298
if (!file(extraJniDirectory).exists()) {

android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/data/DummyRelayItems.kt

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ private val DUMMY_RELAY_1 =
2222
active = true,
2323
provider =
2424
Provider(providerId = ProviderId("PROVIDER RENTED"), ownership = Ownership.Rented),
25+
daita = false,
2526
)
2627
private val DUMMY_RELAY_2 =
2728
RelayItem.Location.Relay(
@@ -33,6 +34,7 @@ private val DUMMY_RELAY_2 =
3334
active = true,
3435
provider =
3536
Provider(providerId = ProviderId("PROVIDER OWNED"), ownership = Ownership.MullvadOwned),
37+
daita = false,
3638
)
3739
private val DUMMY_RELAY_CITY_1 =
3840
RelayItem.Location.City(

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

+12
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ fun FilterRow(
5757
is FilterChip.Ownership ->
5858
OwnershipFilterChip(it.ownership, onRemoveOwnershipFilter)
5959
is FilterChip.Provider -> ProviderFilterChip(it.count, onRemoveProviderFilter)
60+
is FilterChip.Daita -> DaitaFilterChip()
6061
}
6162
}
6263
}
@@ -67,6 +68,7 @@ fun ProviderFilterChip(providers: Int, onRemoveClick: () -> Unit) {
6768
MullvadFilterChip(
6869
text = stringResource(id = R.string.number_of_providers, providers),
6970
onRemoveClick = onRemoveClick,
71+
enabled = true,
7072
)
7173
}
7274

@@ -75,6 +77,16 @@ fun OwnershipFilterChip(ownership: Ownership, onRemoveClick: () -> Unit) {
7577
MullvadFilterChip(
7678
text = stringResource(ownership.stringResources()),
7779
onRemoveClick = onRemoveClick,
80+
enabled = true,
81+
)
82+
}
83+
84+
@Composable
85+
fun DaitaFilterChip() {
86+
MullvadFilterChip(
87+
text = stringResource(id = R.string.setting_chip, stringResource(id = R.string.daita)),
88+
onRemoveClick = {},
89+
enabled = false,
7890
)
7991
}
8092

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/FilterChip.kt

+29-8
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,24 @@ import net.mullvad.mullvadvpn.lib.theme.shape.chipShape
1919

2020
@Preview
2121
@Composable
22-
private fun PreviewMullvadFilterChip() {
22+
private fun PreviewEnabledMullvadFilterChip() {
2323
AppTheme {
2424
MullvadFilterChip(
2525
text = stringResource(id = R.string.number_of_providers),
2626
onRemoveClick = {},
27+
enabled = true,
28+
)
29+
}
30+
}
31+
32+
@Preview
33+
@Composable
34+
private fun PreviewDisabledMullvadFilterChip() {
35+
AppTheme {
36+
MullvadFilterChip(
37+
text = stringResource(id = R.string.number_of_providers),
38+
onRemoveClick = {},
39+
enabled = false,
2740
)
2841
}
2942
}
@@ -36,30 +49,38 @@ fun MullvadFilterChip(
3649
iconColor: Color = MaterialTheme.colorScheme.onPrimary,
3750
text: String,
3851
onRemoveClick: () -> Unit,
52+
enabled: Boolean,
3953
) {
4054
InputChip(
55+
enabled = enabled,
4156
shape = MaterialTheme.shapes.chipShape,
4257
colors =
4358
FilterChipDefaults.filterChipColors(
4459
containerColor = containerColor,
60+
disabledContainerColor = containerColor,
4561
labelColor = labelColor,
62+
disabledLabelColor = labelColor,
4663
iconColor = iconColor,
4764
),
4865
border =
4966
FilterChipDefaults.filterChipBorder(
5067
borderColor = borderColor,
68+
disabledBorderColor = borderColor,
5169
enabled = true,
5270
selected = false,
5371
),
5472
selected = false,
5573
onClick = onRemoveClick,
5674
label = { Text(text = text, style = MaterialTheme.typography.labelMedium) },
57-
trailingIcon = {
58-
Icon(
59-
painter = painterResource(id = R.drawable.icon_close),
60-
contentDescription = null,
61-
modifier = Modifier.size(Dimens.smallIconSize),
62-
)
63-
},
75+
trailingIcon =
76+
if (enabled) {
77+
{
78+
Icon(
79+
painter = painterResource(id = R.drawable.icon_close),
80+
contentDescription = null,
81+
modifier = Modifier.size(Dimens.smallIconSize),
82+
)
83+
}
84+
} else null,
6485
)
6586
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationInfo.kt

+41-9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ private fun PreviewLocationInfo() {
3333
isVisible = true,
3434
isExpanded = true,
3535
location = null,
36+
isUsingDaita = false,
3637
inAddress = null,
3738
outAddress = "",
3839
)
@@ -48,6 +49,7 @@ fun LocationInfo(
4849
isVisible: Boolean,
4950
isExpanded: Boolean,
5051
location: GeoIpLocation?,
52+
isUsingDaita: Boolean,
5153
inAddress: Triple<String, Int, TransportProtocol>?,
5254
outAddress: String,
5355
) {
@@ -61,15 +63,12 @@ fun LocationInfo(
6163
.then(modifier)
6264
) {
6365
Row(verticalAlignment = Alignment.CenterVertically) {
64-
Text(
65-
text = location?.hostname ?: "",
66-
color =
67-
if (isExpanded) {
68-
colorExpanded
69-
} else {
70-
colorCollapsed
71-
},
72-
style = MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.SemiBold),
66+
RelayHostname(
67+
hostname = location?.hostname,
68+
isUsingDaita = isUsingDaita,
69+
isExpanded = isExpanded,
70+
colorExpanded = colorExpanded,
71+
colorCollapsed = colorCollapsed,
7372
)
7473
Chevron(
7574
isExpanded = isExpanded,
@@ -119,3 +118,36 @@ fun LocationInfo(
119118
)
120119
}
121120
}
121+
122+
@Composable
123+
private fun RelayHostname(
124+
hostname: String?,
125+
isUsingDaita: Boolean,
126+
isExpanded: Boolean,
127+
colorExpanded: Color,
128+
colorCollapsed: Color,
129+
) {
130+
val hostnameTitle =
131+
when {
132+
hostname != null && isUsingDaita -> {
133+
stringResource(
134+
id = R.string.connected_using_daita,
135+
hostname,
136+
stringResource(id = R.string.daita),
137+
)
138+
}
139+
hostname != null -> hostname
140+
else -> ""
141+
}
142+
143+
Text(
144+
text = hostnameTitle,
145+
color =
146+
if (isExpanded) {
147+
colorExpanded
148+
} else {
149+
colorCollapsed
150+
},
151+
style = MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.SemiBold),
152+
)
153+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package net.mullvad.mullvadvpn.compose.dialog
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.Spacer
6+
import androidx.compose.foundation.layout.fillMaxWidth
7+
import androidx.compose.foundation.layout.height
8+
import androidx.compose.foundation.rememberScrollState
9+
import androidx.compose.foundation.verticalScroll
10+
import androidx.compose.material3.AlertDialog
11+
import androidx.compose.material3.Icon
12+
import androidx.compose.material3.MaterialTheme
13+
import androidx.compose.material3.Text
14+
import androidx.compose.runtime.Composable
15+
import androidx.compose.ui.Alignment
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.res.painterResource
18+
import androidx.compose.ui.res.stringResource
19+
import androidx.compose.ui.tooling.preview.Preview
20+
import androidx.lifecycle.compose.dropUnlessResumed
21+
import com.ramcosta.composedestinations.annotation.Destination
22+
import com.ramcosta.composedestinations.annotation.RootGraph
23+
import com.ramcosta.composedestinations.result.EmptyResultBackNavigator
24+
import com.ramcosta.composedestinations.result.ResultBackNavigator
25+
import com.ramcosta.composedestinations.spec.DestinationStyle
26+
import net.mullvad.mullvadvpn.R
27+
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
28+
import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar
29+
import net.mullvad.mullvadvpn.lib.theme.AppTheme
30+
import net.mullvad.mullvadvpn.lib.theme.Dimens
31+
import net.mullvad.mullvadvpn.lib.theme.color.AlphaScrollbar
32+
33+
@Preview
34+
@Composable
35+
private fun PreviewDaitaConfirmationDialog() {
36+
AppTheme { DaitaConfirmation(EmptyResultBackNavigator()) }
37+
}
38+
39+
@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
40+
@Composable
41+
fun DaitaConfirmation(navigator: ResultBackNavigator<Boolean>) {
42+
AlertDialog(
43+
onDismissRequest = dropUnlessResumed { navigator.navigateBack(false) },
44+
icon = {
45+
Icon(
46+
modifier = Modifier.fillMaxWidth().height(Dimens.dialogIconHeight),
47+
painter = painterResource(id = R.drawable.icon_alert),
48+
contentDescription = null,
49+
tint = MaterialTheme.colorScheme.onSurface,
50+
)
51+
},
52+
text = {
53+
val scrollState = rememberScrollState()
54+
Column(
55+
Modifier.drawVerticalScrollbar(
56+
scrollState,
57+
MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaScrollbar),
58+
)
59+
.verticalScroll(scrollState),
60+
horizontalAlignment = Alignment.CenterHorizontally,
61+
) {
62+
Text(
63+
text = stringResource(id = R.string.daita_relay_subset_warning),
64+
color = MaterialTheme.colorScheme.onSurface,
65+
style = MaterialTheme.typography.bodySmall,
66+
modifier = Modifier.fillMaxWidth(),
67+
)
68+
69+
Spacer(modifier = Modifier.height(Dimens.verticalSpace))
70+
71+
Text(
72+
text =
73+
stringResource(
74+
id = R.string.daita_warning,
75+
stringResource(id = R.string.daita),
76+
),
77+
color = MaterialTheme.colorScheme.onSurface,
78+
style = MaterialTheme.typography.bodySmall,
79+
modifier = Modifier.fillMaxWidth(),
80+
)
81+
}
82+
},
83+
confirmButton = {
84+
Column(verticalArrangement = Arrangement.spacedBy(Dimens.buttonSpacing)) {
85+
PrimaryButton(
86+
modifier = Modifier.fillMaxWidth(),
87+
text = stringResource(R.string.enable_anyway),
88+
onClick = { navigator.navigateBack(true) },
89+
)
90+
91+
PrimaryButton(
92+
modifier = Modifier.fillMaxWidth(),
93+
text = stringResource(R.string.back),
94+
onClick = dropUnlessResumed { navigator.navigateBack(false) },
95+
)
96+
}
97+
},
98+
containerColor = MaterialTheme.colorScheme.surface,
99+
titleContentColor = MaterialTheme.colorScheme.onSurface,
100+
)
101+
}

0 commit comments

Comments
 (0)