summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2025-07-28 14:38:49 +0200
committerDavid Göransson <david.goransson@mullvad.net>2025-07-28 14:38:49 +0200
commit4467d98ce03bc3057f68dc19ad17b71c44eb3501 (patch)
treec25463ab47568fb73727646c2ce4d0414c6f7bcd
parente2d91ff3d404d17a66c925bc5cd22dc29417550b (diff)
parent235c1446b096d40e6ee686878391732a41c0fefb (diff)
downloadmullvadvpn-4467d98ce03bc3057f68dc19ad17b71c44eb3501.tar.xz
mullvadvpn-4467d98ce03bc3057f68dc19ad17b71c44eb3501.zip
Merge branch 'detekt-named-args-droid-1528'
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateCustomListDialog.kt15
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeleteCustomListConfirmationDialog.kt4
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt41
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/EditCustomListNameDialog.kt9
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ResetServerIpOverridesConfirmationDialog.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/SaveApiAccessMethodDialog.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessListScreen.kt10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessMethodDetailsScreen.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogScreen.kt46
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt28
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreen.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListsScreen.kt10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DaitaScreen.kt8
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditApiAccessMethodScreen.kt24
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditCustomListScreen.kt10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ImportOverridesByTextScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ManageDevicesScreen.kt10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt4
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/NoDaemonScreen.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt9
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt14
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ServerIpOverridesScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt14
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ShadowsocksSettingsScreen.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/Udp2TcpSettingsScreen.kt7
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt26
-rw-r--r--android/build.gradle.kts5
-rw-r--r--android/gradle/libs.versions.toml5
-rw-r--r--android/gradle/verification-metadata.xml31
-rw-r--r--android/settings.gradle.kts3
-rw-r--r--android/test/detekt/build.gradle.kts10
-rw-r--r--android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/CustomProvider.kt14
-rw-r--r--android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/rules/ScreenAndDialogNamedArguments.kt50
-rw-r--r--android/test/detekt/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider1
-rw-r--r--android/test/detekt/src/main/resources/config/config.yml4
-rw-r--r--android/test/detekt/src/test/kotlin/net/mullvad/mullvadvpn/detekt/extensions/ScreenAndDialogNamedArgumentsTest.kt98
43 files changed, 502 insertions, 109 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateCustomListDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateCustomListDialog.kt
index 15b262bdf7..41b3574d0d 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateCustomListDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateCustomListDialog.kt
@@ -33,7 +33,14 @@ import org.koin.androidx.compose.koinViewModel
@Preview
@Composable
private fun PreviewCreateCustomListDialog() {
- AppTheme { CreateCustomListDialog(state = CreateCustomListUiState(), {}, {}, {}) }
+ AppTheme {
+ CreateCustomListDialog(
+ state = CreateCustomListUiState(),
+ createCustomList = {},
+ onInputChanged = {},
+ onDismiss = {},
+ )
+ }
}
@Preview
@@ -45,9 +52,9 @@ private fun PreviewCreateCustomListDialogError() {
CreateCustomListUiState(
error = CreateWithLocationsError.Create(CustomListAlreadyExists)
),
- {},
- {},
- {},
+ createCustomList = {},
+ onInputChanged = {},
+ onDismiss = {},
)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeleteCustomListConfirmationDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeleteCustomListConfirmationDialog.kt
index 1dffa3bfc9..4137f425e4 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeleteCustomListConfirmationDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeleteCustomListConfirmationDialog.kt
@@ -27,8 +27,8 @@ private fun PreviewRemoveDeviceConfirmationDialog() {
AppTheme {
DeleteCustomListConfirmationDialog(
state = DeleteCustomListUiState(CustomListName.fromString("My Custom List"), null),
- {},
- {},
+ onDelete = {},
+ onBack = {},
)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt
index 1c1247de67..bf8a8b0989 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialog.kt
@@ -27,19 +27,50 @@ import org.koin.androidx.compose.koinViewModel
@Preview
@Composable
private fun PreviewDnsDialogNew() {
- AppTheme { DnsDialog(DnsDialogViewState("1.1.1.1", null, false, false, null), {}, {}, {}, {}) }
+ AppTheme {
+ DnsDialog(
+ state = DnsDialogViewState("1.1.1.1", null, false, false, null),
+ onDnsInputChange = {},
+ onSaveDnsClick = {},
+ onRemoveDnsClick = {},
+ onDismiss = {},
+ )
+ }
}
@Preview
@Composable
private fun PreviewDnsDialogEdit() {
- AppTheme { DnsDialog(DnsDialogViewState("1.1.1.1", null, false, false, 0), {}, {}, {}, {}) }
+ AppTheme {
+ DnsDialog(
+ state =
+ DnsDialogViewState(
+ input = "1.1.1.1",
+ validationError = null,
+ isAllowLanEnabled = false,
+ isIpv6Enabled = false,
+ index = 0,
+ ),
+ onDnsInputChange = {},
+ onSaveDnsClick = {},
+ onRemoveDnsClick = {},
+ onDismiss = {},
+ )
+ }
}
@Preview
@Composable
private fun PreviewDnsDialogEditAllowLanDisabled() {
- AppTheme { DnsDialog(DnsDialogViewState("192.168.1.1", null, false, false, 0), {}, {}, {}, {}) }
+ AppTheme {
+ DnsDialog(
+ state = DnsDialogViewState("192.168.1.1", null, false, false, 0),
+ onDnsInputChange = {},
+ onSaveDnsClick = {},
+ onRemoveDnsClick = {},
+ onDismiss = {},
+ )
+ }
}
data class DnsDialogNavArgs(val index: Int? = null, val initialValue: String? = null)
@@ -60,8 +91,8 @@ fun Dns(resultNavigator: ResultBackNavigator<DnsDialogResult>) {
val state by viewModel.uiState.collectAsStateWithLifecycle()
DnsDialog(
- state,
- viewModel::onDnsInputChange,
+ state = state,
+ onDnsInputChange = viewModel::onDnsInputChange,
onSaveDnsClick = viewModel::onSaveDnsClick,
onRemoveDnsClick = viewModel::onRemoveDnsClick,
onDismiss = dropUnlessResumed { resultNavigator.navigateBack() },
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/EditCustomListNameDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/EditCustomListNameDialog.kt
index 7fdd9b5b7a..897106e3bf 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/EditCustomListNameDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/EditCustomListNameDialog.kt
@@ -32,7 +32,14 @@ import org.koin.androidx.compose.koinViewModel
@Preview
@Composable
private fun PreviewEditCustomListNameDialog() {
- AppTheme { EditCustomListNameDialog(EditCustomListNameUiState(), {}, {}, {}) }
+ AppTheme {
+ EditCustomListNameDialog(
+ state = EditCustomListNameUiState(),
+ updateName = {},
+ onInputChanged = {},
+ onDismiss = {},
+ )
+ }
}
data class EditCustomListNameNavArgs(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt
index 97427fe9da..e1ee0a0faf 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialog.kt
@@ -54,7 +54,7 @@ fun Mtu(navigator: ResultBackNavigator<Boolean>) {
}
}
MtuDialog(
- uiState,
+ state = uiState,
onInputChanged = viewModel::onInputChanged,
onSaveMtu = viewModel::onSaveClick,
onResetMtu = viewModel::onRestoreClick,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ResetServerIpOverridesConfirmationDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ResetServerIpOverridesConfirmationDialog.kt
index 950af0c9f9..f4648a8ccd 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ResetServerIpOverridesConfirmationDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ResetServerIpOverridesConfirmationDialog.kt
@@ -28,7 +28,9 @@ import org.koin.androidx.compose.koinViewModel
@Preview
@Composable
private fun PreviewResetServerIpOverridesConfirmationDialog() {
- AppTheme { ResetServerIpOverridesConfirmationDialog({}, {}) }
+ AppTheme {
+ ResetServerIpOverridesConfirmationDialog(onClearAllOverrides = {}, onNavigateBack = {})
+ }
}
@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
@@ -45,7 +47,7 @@ fun ResetServerIpOverridesConfirmation(resultBackNavigator: ResultBackNavigator<
}
ResetServerIpOverridesConfirmationDialog(
onClearAllOverrides = vm::clearAllOverrides,
- dropUnlessResumed { resultBackNavigator.navigateBack() },
+ onNavigateBack = dropUnlessResumed { resultBackNavigator.navigateBack() },
)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/SaveApiAccessMethodDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/SaveApiAccessMethodDialog.kt
index d9e649883c..b0dd65858d 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/SaveApiAccessMethodDialog.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/SaveApiAccessMethodDialog.kt
@@ -42,7 +42,7 @@ private fun PreviewSaveApiAccessMethodDialog(
@PreviewParameter(SaveApiAccessMethodUiStatePreviewParameterProvider::class)
state: SaveApiAccessMethodUiState
) {
- AppTheme { SaveApiAccessMethodDialog(state = state, {}, {}) }
+ AppTheme { SaveApiAccessMethodDialog(state = state, onCancel = {}, onSave = {}) }
}
data class SaveApiAccessMethodNavArgs(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessListScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessListScreen.kt
index 22c34514fb..f84c7cd2ba 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessListScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessListScreen.kt
@@ -51,7 +51,15 @@ private fun PreviewApiAccessList(
@PreviewParameter(ApiAccessListUiStatePreviewParameterProvider::class)
state: ApiAccessListUiState
) {
- AppTheme { ApiAccessListScreen(state = state, {}, { _ -> }, {}, {}) }
+ AppTheme {
+ ApiAccessListScreen(
+ state = state,
+ onAddMethodClick = {},
+ onApiAccessMethodClick = { _ -> },
+ onApiAccessInfoClick = {},
+ onBackClick = {},
+ )
+ }
}
@Destination<RootGraph>(style = SlideInFromRightTransition::class)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessMethodDetailsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessMethodDetailsScreen.kt
index b59fce4f06..f858db8375 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessMethodDetailsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ApiAccessMethodDetailsScreen.kt
@@ -78,7 +78,17 @@ private fun PreviewApiAccessMethodDetailsScreen(
state: ApiAccessMethodDetailsUiState
) {
AppTheme {
- ApiAccessMethodDetailsScreen(state = state, SnackbarHostState(), {}, {}, {}, {}, {}, {}, {})
+ ApiAccessMethodDetailsScreen(
+ state = state,
+ snackbarHostState = SnackbarHostState(),
+ onEditMethodClicked = {},
+ onEnableClicked = {},
+ onTestMethodClicked = {},
+ onUseMethodClicked = {},
+ onDeleteApiAccessMethodClicked = {},
+ onNavigateToEncryptedDnsInfoDialog = {},
+ onBackClicked = {},
+ )
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogScreen.kt
index 2ae10213ab..cb0d063150 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogScreen.kt
@@ -45,7 +45,7 @@ fun Changelog(navController: NavController) {
LaunchedEffect(Unit) { viewModel.dismissChangelogNotification() }
- ChangelogScreen(uiState.value, onBackClick = navController::navigateUp)
+ ChangelogScreen(state = uiState.value, onBackClick = navController::navigateUp)
}
data class ChangelogNavArgs(val isModal: Boolean = false)
@@ -120,7 +120,7 @@ private fun ChangeListItem(text: String) {
private fun PreviewChangelogDialogWithSingleShortItem() {
AppTheme {
ChangelogScreen(
- ChangelogUiState(changes = listOf("Item 1"), version = "1111.1"),
+ state = ChangelogUiState(changes = listOf("Item 1"), version = "1111.1"),
onBackClick = {},
)
}
@@ -136,10 +136,11 @@ private fun PreviewChangelogDialogWithTwoLongItems() {
AppTheme {
ChangelogScreen(
- ChangelogUiState(
- changes = listOf(longPreviewText, longPreviewText),
- version = "1111.1",
- ),
+ state =
+ ChangelogUiState(
+ changes = listOf(longPreviewText, longPreviewText),
+ version = "1111.1",
+ ),
onBackClick = {},
)
}
@@ -150,22 +151,23 @@ private fun PreviewChangelogDialogWithTwoLongItems() {
private fun PreviewChangelogDialogWithTenShortItems() {
AppTheme {
ChangelogScreen(
- ChangelogUiState(
- changes =
- listOf(
- "Item 1",
- "Item 2",
- "Item 3",
- "Item 4",
- "Item 5",
- "Item 6",
- "Item 7",
- "Item 8",
- "Item 9",
- "Item 10",
- ),
- version = "1111.1",
- ),
+ state =
+ ChangelogUiState(
+ changes =
+ listOf(
+ "Item 1",
+ "Item 2",
+ "Item 3",
+ "Item 4",
+ "Item 5",
+ "Item 6",
+ "Item 7",
+ "Item 8",
+ "Item 9",
+ "Item 10",
+ ),
+ version = "1111.1",
+ ),
onBackClick = {},
)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
index 88a4c30922..8f7775c613 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
@@ -150,20 +150,20 @@ private fun PreviewAccountScreen(
ConnectScreen(
state = state,
snackbarHostState = SnackbarHostState(),
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
+ onDisconnectClick = {},
+ onReconnectClick = {},
+ onConnectClick = {},
+ onCancelClick = {},
+ onSwitchLocationClick = {},
+ onOpenAppListing = {},
+ onManageAccountClick = {},
+ onChangelogClick = {},
+ onDismissChangelogClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onDismissNewDeviceClick = {},
+ onNavigateToFeature = {},
+ onClickShowWireguardPortSettings = {},
)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreen.kt
index 6aea279110..95611ccf5e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreen.kt
@@ -69,7 +69,16 @@ private fun PreviewCustomListLocationScreen(
@PreviewParameter(CustomListLocationUiStatePreviewParameterProvider::class)
state: CustomListLocationsUiState
) {
- AppTheme { CustomListLocationsScreen(state = state, {}, {}, { _, _ -> }, { _, _ -> }, {}) }
+ AppTheme {
+ CustomListLocationsScreen(
+ state = state,
+ onSearchTermInput = {},
+ onSaveClick = {},
+ onRelaySelectionClick = { _, _ -> },
+ onExpand = { _, _ -> },
+ onBackClick = {},
+ )
+ }
}
data class CustomListLocationsNavArgs(val customListId: CustomListId, val newList: Boolean)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListsScreen.kt
index 32cc2608f6..4707902ff0 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListsScreen.kt
@@ -58,7 +58,15 @@ import org.koin.androidx.compose.koinViewModel
private fun PreviewAccountScreen(
@PreviewParameter(CustomListsUiStatePreviewParameterProvider::class) state: CustomListsUiState
) {
- AppTheme { CustomListsScreen(state = state, SnackbarHostState(), {}, { _ -> }, {}) }
+ AppTheme {
+ CustomListsScreen(
+ state = state,
+ snackbarHostState = SnackbarHostState(),
+ addCustomList = {},
+ openCustomList = { _ -> },
+ onBackClick = {},
+ )
+ }
}
@Composable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DaitaScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DaitaScreen.kt
index ffa4afbd9a..7d451b9253 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DaitaScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DaitaScreen.kt
@@ -63,10 +63,10 @@ private fun PreviewDaitaScreen() {
AppTheme {
DaitaScreen(
state = DaitaUiState(daitaEnabled = false, directOnly = false),
- { _ -> },
- { _ -> },
- {},
- {},
+ onDaitaEnabled = { _ -> },
+ onDirectOnlyClick = { _ -> },
+ onDirectOnlyInfoClick = {},
+ onBackClick = {},
)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt
index a4ad010775..fa2a30bc83 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt
@@ -65,7 +65,17 @@ import org.koin.androidx.compose.koinViewModel
private fun PreviewDeviceListScreenContent(
@PreviewParameter(DeviceListUiStatePreviewParameterProvider::class) state: DeviceListUiState
) {
- AppTheme { DeviceListScreen(state = state, SnackbarHostState(), {}, {}, {}, {}, {}) }
+ AppTheme {
+ DeviceListScreen(
+ state = state,
+ snackbarHostState = SnackbarHostState(),
+ onBackClick = {},
+ onContinueWithLogin = {},
+ onSettingsClicked = {},
+ onTryAgainClicked = {},
+ navigateToRemoveDeviceConfirmationDialog = {},
+ )
+ }
}
data class DeviceListNavArgs(val accountNumber: AccountNumber)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt
index 9baca47b00..0cbd6d8836 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt
@@ -47,7 +47,7 @@ private fun PreviewDeviceRevokedScreen(
@PreviewParameter(DeviceRevokedUiStatePreviewParameterProvider::class)
state: DeviceRevokedUiState
) {
- AppTheme { DeviceRevokedScreen(state = state, {}, {}) }
+ AppTheme { DeviceRevokedScreen(state = state, onSettingsClicked = {}, onGoToLoginClicked = {}) }
}
@Destination<RootGraph>
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditApiAccessMethodScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditApiAccessMethodScreen.kt
index 3b4ead576e..a924b49441 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditApiAccessMethodScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditApiAccessMethodScreen.kt
@@ -85,18 +85,18 @@ private fun PreviewEditApiAccessMethodScreen(
AppTheme {
EditApiAccessMethodScreen(
state = state,
- SnackbarHostState(),
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
- {},
+ snackbarHostState = SnackbarHostState(),
+ onNameChanged = {},
+ onTypeSelected = {},
+ onIpChanged = {},
+ onPortChanged = {},
+ onPasswordChanged = {},
+ onCipherChange = {},
+ onToggleAuthenticationEnabled = {},
+ onUsernameChanged = {},
+ onTestMethod = {},
+ onAddMethod = {},
+ onNavigateBack = {},
)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditCustomListScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditCustomListScreen.kt
index 5c7ff4642a..95003ada38 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditCustomListScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/EditCustomListScreen.kt
@@ -61,7 +61,15 @@ private fun PreviewEditCustomListScreen(
@PreviewParameter(EditCustomListUiStatePreviewParameterProvider::class)
state: EditCustomListUiState
) {
- AppTheme { EditCustomListScreen(state = state, { _, _ -> }, { _, _ -> }, {}, {}) }
+ AppTheme {
+ EditCustomListScreen(
+ state = state,
+ onDeleteList = { _, _ -> },
+ onNameClicked = { _, _ -> },
+ onLocationsClicked = {},
+ onBackClick = {},
+ )
+ }
}
data class EditCustomListNavArgs(val customListId: CustomListId)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ImportOverridesByTextScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ImportOverridesByTextScreen.kt
index 228cfff16f..a1c161c077 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ImportOverridesByTextScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ImportOverridesByTextScreen.kt
@@ -34,7 +34,7 @@ import net.mullvad.mullvadvpn.lib.theme.AppTheme
@Preview
@Composable
private fun PreviewImportOverridesByText() {
- AppTheme { ImportOverridesByTextScreen({}, {}) }
+ AppTheme { ImportOverridesByTextScreen(onNavigateBack = {}, onImportClicked = {}) }
}
@Destination<RootGraph>(style = DefaultTransition::class)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt
index 7a73cb16e4..a026856b29 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt
@@ -98,7 +98,17 @@ import org.koin.androidx.compose.koinViewModel
private fun PreviewLoginScreen(
@PreviewParameter(LoginUiStatePreviewParameterProvider::class) state: LoginUiState
) {
- AppTheme { LoginScreen(state = state, SnackbarHostState(), {}, {}, {}, {}, {}) }
+ AppTheme {
+ LoginScreen(
+ state = state,
+ snackbarHostState = SnackbarHostState(),
+ onLoginClick = {},
+ onCreateAccountClick = {},
+ onDeleteHistoryClick = {},
+ onAccountNumberChange = {},
+ onSettingsClick = {},
+ )
+ }
}
private const val TOP_SPACER_WEIGHT = 1f
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ManageDevicesScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ManageDevicesScreen.kt
index d7ab455f09..0cc7b4c1f8 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ManageDevicesScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ManageDevicesScreen.kt
@@ -56,7 +56,15 @@ private fun PreviewDeviceListScreenContent(
@PreviewParameter(ManageDevicesUiStatePreviewParameterProvider::class)
state: Lce<Unit, ManageDevicesUiState, GetDeviceListError>
) {
- AppTheme { ManageDevicesScreen(state = state, SnackbarHostState(), {}, {}, {}) }
+ AppTheme {
+ ManageDevicesScreen(
+ state = state,
+ snackbarHostState = SnackbarHostState(),
+ onBackClick = {},
+ onTryAgainClicked = {},
+ navigateToRemoveDeviceConfirmationDialog = {},
+ )
+ }
}
private typealias StateLce = Lce<Unit, ManageDevicesUiState, GetDeviceListError>
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt
index ba5f854f03..769b028a70 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt
@@ -43,7 +43,9 @@ import org.koin.androidx.compose.koinViewModel
@Preview
@Composable
private fun PreviewMultihopScreen() {
- AppTheme { MultihopScreen(state = MultihopUiState(false), {}, {}) }
+ AppTheme {
+ MultihopScreen(state = MultihopUiState(false), onMultihopClick = {}, onBackClick = {})
+ }
}
@Parcelize data class MultihopNavArgs(val isModal: Boolean = false) : Parcelable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/NoDaemonScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/NoDaemonScreen.kt
index d7bebb4016..10bb70a733 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/NoDaemonScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/NoDaemonScreen.kt
@@ -37,14 +37,16 @@ import net.mullvad.mullvadvpn.util.getActivity
@Preview
@Composable
private fun PreviewNoDaemonScreen() {
- AppTheme { NoDaemonScreen({}) }
+ AppTheme { NoDaemonScreen(onNavigateToSettings = {}) }
}
// Set this as the start destination of the default nav graph
@Destination<RootGraph>(style = DefaultTransition::class)
@Composable
fun NoDaemon(navigator: DestinationsNavigator) {
- NoDaemonScreen(dropUnlessResumed { navigator.navigate(SettingsDestination) })
+ NoDaemonScreen(
+ onNavigateToSettings = dropUnlessResumed { navigator.navigate(SettingsDestination) }
+ )
}
@Composable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt
index 08d97019e4..1defeddb2e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt
@@ -71,7 +71,17 @@ import org.koin.androidx.compose.koinViewModel
private fun PreviewOutOfTimeScreen(
@PreviewParameter(OutOfTimeScreenPreviewParameterProvider::class) state: OutOfTimeUiState
) {
- AppTheme { OutOfTimeScreen(state = state, SnackbarHostState(), {}, {}, {}, {}, {}) }
+ AppTheme {
+ OutOfTimeScreen(
+ state = state,
+ snackbarHostState = SnackbarHostState(),
+ onDisconnectClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onRedeemVoucherClick = {},
+ onPlayPaymentInfoClick = {},
+ )
+ }
}
@Destination<RootGraph>(style = HomeTransition::class)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt
index 85f9e893c0..ed1c10b39a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt
@@ -62,8 +62,8 @@ import org.koin.androidx.compose.koinViewModel
private fun PreviewPrivacyDisclaimerScreen() {
AppTheme {
PrivacyDisclaimerScreen(
- PrivacyDisclaimerViewState(isStartingService = false, isPlayBuild = false),
- {},
+ state = PrivacyDisclaimerViewState(isStartingService = false, isPlayBuild = false),
+ onAcceptClicked = {},
)
}
}
@@ -101,7 +101,10 @@ fun PrivacyDisclaimer(navigator: DestinationsNavigator) {
}
}
}
- PrivacyDisclaimerScreen(state, viewModel::setPrivacyDisclosureAccepted)
+ PrivacyDisclaimerScreen(
+ state = state,
+ onAcceptClicked = viewModel::setPrivacyDisclosureAccepted,
+ )
}
@Composable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt
index ddb6bdcaf6..699a71a164 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt
@@ -75,7 +75,17 @@ private fun PreviewReportProblemScreen(
@PreviewParameter(ReportProblemUiStatePreviewParameterProvider::class)
state: ReportProblemUiState
) {
- AppTheme { ReportProblemScreen(state = state, {}, {}, {}, {}, {}, {}) }
+ AppTheme {
+ ReportProblemScreen(
+ state = state,
+ onSendReport = {},
+ onClearSendResult = {},
+ onNavigateToViewLogs = {},
+ onEmailChanged = {},
+ onDescriptionChanged = {},
+ onBackClick = {},
+ )
+ }
}
@Destination<RootGraph>(style = SlideInFromRightTransition::class)
@@ -102,7 +112,7 @@ fun ReportProblem(
}
ReportProblemScreen(
- state,
+ state = state,
onSendReport = { vm.sendReport(state.email, state.description) },
onClearSendResult = vm::clearSendResult,
onNavigateToViewLogs =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ServerIpOverridesScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ServerIpOverridesScreen.kt
index ae80cb07f7..78cd0e371d 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ServerIpOverridesScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ServerIpOverridesScreen.kt
@@ -166,7 +166,7 @@ fun SharedTransitionScope.ServerIpOverrides(
}
ServerIpOverridesScreen(
- state,
+ state = state,
onBackClick = dropUnlessResumed { navigator.navigateUp() },
onInfoClick = dropUnlessResumed { navigator.navigate(ServerIpOverridesInfoDestination) },
onResetOverridesClick =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt
index d75400322f..2b129f8b4c 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt
@@ -58,7 +58,19 @@ import org.koin.androidx.compose.koinViewModel
private fun PreviewSettingsScreen(
@PreviewParameter(SettingsUiStatePreviewParameterProvider::class) state: SettingsUiState
) {
- AppTheme { SettingsScreen(state = state, {}, {}, {}, {}, {}, {}, {}, {}) }
+ AppTheme {
+ SettingsScreen(
+ state = state,
+ onVpnSettingCellClick = {},
+ onSplitTunnelingCellClick = {},
+ onAppInfoClick = {},
+ onReportProblemCellClick = {},
+ onApiAccessClick = {},
+ onMultihopClick = {},
+ onDaitaClick = {},
+ onBackClick = {},
+ )
+ }
}
@OptIn(ExperimentalMaterial3Api::class)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ShadowsocksSettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ShadowsocksSettingsScreen.kt
index fcd6603941..4dbdc50f7a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ShadowsocksSettingsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ShadowsocksSettingsScreen.kt
@@ -40,9 +40,9 @@ private fun PreviewShadowsocksSettingsScreen() {
AppTheme {
ShadowsocksSettingsScreen(
state = ShadowsocksSettingsState(port = Constraint.Any, validPortRanges = emptyList()),
- {},
- {},
- {},
+ navigateToCustomPortDialog = {},
+ onObfuscationPortSelected = {},
+ onBackClick = {},
)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
index 1e3a2766ec..aba3996803 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
@@ -66,7 +66,17 @@ private fun PreviewSplitTunnelingScreen(
@PreviewParameter(SplitTunnelingUiStatePreviewParameterProvider::class)
state: SplitTunnelingUiState
) {
- AppTheme { SplitTunnelingScreen(state = state, {}, {}, {}, {}, {}, { null }) }
+ AppTheme {
+ SplitTunnelingScreen(
+ state = state,
+ onEnableSplitTunneling = {},
+ onShowSystemAppsClick = {},
+ onExcludeAppClick = {},
+ onIncludeAppClick = {},
+ onBackClick = {},
+ onResolveIcon = { null },
+ )
+ }
}
@Parcelize data class SplitTunnelingNavArgs(val isModal: Boolean = false) : Parcelable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/Udp2TcpSettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/Udp2TcpSettingsScreen.kt
index 9f8499b31f..94a473dd5c 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/Udp2TcpSettingsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/Udp2TcpSettingsScreen.kt
@@ -32,7 +32,12 @@ import org.koin.androidx.compose.koinViewModel
@Composable
private fun PreviewUdp2TcpSettingsScreen() {
AppTheme {
- Udp2TcpSettingsScreen(state = Udp2TcpSettingsState(port = Constraint.Any), {}, {}, {})
+ Udp2TcpSettingsScreen(
+ state = Udp2TcpSettingsState(port = Constraint.Any),
+ onObfuscationPortSelected = {},
+ navigateUdp2TcpInfo = {},
+ onBackClick = {},
+ )
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt
index 085060db48..76ed0879eb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt
@@ -63,7 +63,7 @@ import org.koin.androidx.compose.koinViewModel
private fun PreviewViewLogsScreen(
@PreviewParameter(ViewLogsUiStatePreviewParameterProvider::class) state: ViewLogsUiState
) {
- AppTheme { ViewLogsScreen(state = state, {}) }
+ AppTheme { ViewLogsScreen(state = state, onBackClick = {}) }
}
@Destination<RootGraph>(style = SlideInFromRightTransition::class)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt
index 1b512b20b5..f3893dcd40 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt
@@ -89,19 +89,19 @@ private fun PreviewSearchLocationScreen(
AppTheme {
SearchLocationScreen(
state = state,
- SnackbarHostState(),
- {},
- { _, _, _ -> },
- {},
- {},
- { _, _ -> },
- { _, _ -> },
- {},
- {},
- {},
- {},
- {},
- {},
+ snackbarHostState = SnackbarHostState(),
+ onSelectHop = {},
+ onToggleExpand = { _, _, _ -> },
+ onSearchInputChanged = {},
+ onCreateCustomList = {},
+ onAddLocationToList = { _, _ -> },
+ onRemoveLocationFromList = { _, _ -> },
+ onEditCustomListName = {},
+ onEditLocationsCustomList = {},
+ onDeleteCustomList = {},
+ onRemoveOwnershipFilter = {},
+ onRemoveProviderFilter = {},
+ onGoBack = {},
)
}
}
diff --git a/android/build.gradle.kts b/android/build.gradle.kts
index b79254868c..5bbe5e8a00 100644
--- a/android/build.gradle.kts
+++ b/android/build.gradle.kts
@@ -84,9 +84,14 @@ detekt {
parallel = true
ignoreFailures = false
autoCorrect = true
+
+ dependencies {
+ detektPlugins(project(":test:detekt"))
+ }
}
tasks.withType<Detekt>().configureEach {
+ dependsOn(":test:detekt:assemble")
// Ignore generated files from the build directory, e.g files created by ksp.
exclude(detektExcludedPaths)
}
diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml
index e943b215b5..61b3c16d7a 100644
--- a/android/gradle/libs.versions.toml
+++ b/android/gradle/libs.versions.toml
@@ -154,6 +154,7 @@ grpc-protobuf-lite = { module = "io.grpc:grpc-protobuf-lite", version.ref = "grp
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
+junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version = "junit" }
junit5-android-test-compose = { module = "de.mannodermaus.junit5:android-test-compose", version.ref = "junit5-android" }
junit5-android-test-core = { module = "de.mannodermaus.junit5:android-test-core", version.ref = "junit5-android" }
@@ -193,6 +194,10 @@ ktor-client-resources = { module = "io.ktor:ktor-client-resources", version.ref
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk" }
+# Detekt
+detekt-api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" }
+detekt-test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" }
+
# Misc
commons-validator = { module = "commons-validator:commons-validator", version.ref = "commonsvalidator" }
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
diff --git a/android/gradle/verification-metadata.xml b/android/gradle/verification-metadata.xml
index eeee6be84b..452ae7e5cc 100644
--- a/android/gradle/verification-metadata.xml
+++ b/android/gradle/verification-metadata.xml
@@ -4246,6 +4246,22 @@
<sha256 value="1531e20afbc40b27bd6284802ca5935f0357d7d951cd6420a47f72fb28630e7a" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="io.gitlab.arturbosch.detekt" name="detekt-test" version="1.23.8">
+ <artifact name="detekt-test-1.23.8.jar">
+ <sha256 value="5383c41e5f22c8def6f890bd66820fe9ff438835600525fdf6eba96742499351" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="detekt-test-1.23.8.module">
+ <sha256 value="03bba627552816a8e6d2562ca2c14d1945eddc3ff3cb1e6d5c61364e9ec5e24c" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="io.gitlab.arturbosch.detekt" name="detekt-test-utils" version="1.23.8">
+ <artifact name="detekt-test-utils-1.23.8.jar">
+ <sha256 value="c27c0673cad7cc1f2e932c89a060b7ae85749a03d69f221b4c1281f64136c702" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="detekt-test-utils-1.23.8.module">
+ <sha256 value="9f3925672dc335fc7d246ac4d9ab5f6b26e4ee91c37176a3e79b2c799c925562" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="io.gitlab.arturbosch.detekt" name="detekt-tooling" version="1.23.8">
<artifact name="detekt-tooling-1.23.8.jar">
<sha256 value="7e93e9a23b478f70128893b06748673f912100b7ef03040d7d0331e26d30d092" origin="Generated by Gradle"/>
@@ -5898,6 +5914,11 @@
<sha256 value="28417e19977aa498dc08993aae201ffc21b94e9ff422f522522d608f606b9206" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="org.jetbrains.kotlin" name="kotlin-main-kts" version="2.0.21">
+ <artifact name="kotlin-main-kts-2.0.21.jar">
+ <sha256 value="36fef581638be9c674295c176f10bc9f13025e5e1160030200991ded62ed6c29" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="org.jetbrains.kotlin" name="kotlin-metadata-jvm" version="2.2.0">
<artifact name="kotlin-metadata-jvm-2.2.0.jar">
<sha256 value="501222ae7d63527e55f2e5e645f18d4eff2c19074c85b9bc055866e3ed2b17bf" origin="Generated by Gradle"/>
@@ -6182,6 +6203,11 @@
<sha256 value="af1ec40c3b951afdcc0c2a0173c7b81763c5281c2d5bafbf0a8544a24c5dcc0c" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="2.0.21">
+ <artifact name="kotlin-stdlib-jdk7-2.0.21.jar">
+ <sha256 value="712f480760edeee48a84369e6be89f6ab52375408bb2ca3be14ef663f72bee31" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="2.1.0">
<artifact name="kotlin-stdlib-jdk7-2.1.0.jar">
<sha256 value="fdea6c4203724f42e8e64bef2f0bf79129ccd1df1edf1ccffdc22de7df498c76" origin="Generated by Gradle"/>
@@ -6212,6 +6238,11 @@
<sha256 value="e398b67977622718bf18ff99b739c7d9da060f33fb458a2e25203221c16af010" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="2.0.21">
+ <artifact name="kotlin-stdlib-jdk8-2.0.21.jar">
+ <sha256 value="15c8c0acb311483c068d1697501965474b70dfd80ac79580eca3a03cf51e4a1d" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="2.1.0">
<artifact name="kotlin-stdlib-jdk8-2.1.0.jar">
<sha256 value="238d3c7e492f119b50da1c22546dd762462e55f22409611f5e53dd77625cd544" origin="Generated by Gradle"/>
diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts
index 0d3df97602..7840eb33d7 100644
--- a/android/settings.gradle.kts
+++ b/android/settings.gradle.kts
@@ -38,5 +38,6 @@ include(
":test:arch",
":test:common",
":test:e2e",
- ":test:mockapi"
+ ":test:mockapi",
+ ":test:detekt",
)
diff --git a/android/test/detekt/build.gradle.kts b/android/test/detekt/build.gradle.kts
new file mode 100644
index 0000000000..92f34e4c6b
--- /dev/null
+++ b/android/test/detekt/build.gradle.kts
@@ -0,0 +1,10 @@
+plugins { kotlin("jvm") }
+
+dependencies {
+ compileOnly(libs.detekt.api)
+ testImplementation(libs.detekt.test)
+ testImplementation(libs.junit.jupiter.engine)
+ testRuntimeOnly(libs.junit.platform.launcher)
+}
+
+tasks.withType<Test> { useJUnitPlatform() }
diff --git a/android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/CustomProvider.kt b/android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/CustomProvider.kt
new file mode 100644
index 0000000000..4b7c62a93f
--- /dev/null
+++ b/android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/CustomProvider.kt
@@ -0,0 +1,14 @@
+package net.mullvad.mullvadvpn.detekt.extensions
+
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.RuleSet
+import io.gitlab.arturbosch.detekt.api.RuleSetProvider
+import net.mullvad.mullvadvpn.detekt.extensions.rules.ScreenAndDialogNamedArguments
+
+class CustomProvider : RuleSetProvider {
+
+ override val ruleSetId: String = "custom"
+
+ override fun instance(config: Config): RuleSet =
+ RuleSet(ruleSetId, listOf(ScreenAndDialogNamedArguments(config)))
+}
diff --git a/android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/rules/ScreenAndDialogNamedArguments.kt b/android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/rules/ScreenAndDialogNamedArguments.kt
new file mode 100644
index 0000000000..cd458ddea9
--- /dev/null
+++ b/android/test/detekt/src/main/kotlin/net/mullvad/mullvadvpn/detekt/extensions/rules/ScreenAndDialogNamedArguments.kt
@@ -0,0 +1,50 @@
+package net.mullvad.mullvadvpn.detekt.extensions.rules
+
+import io.gitlab.arturbosch.detekt.api.CodeSmell
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.Debt
+import io.gitlab.arturbosch.detekt.api.Entity
+import io.gitlab.arturbosch.detekt.api.Issue
+import io.gitlab.arturbosch.detekt.api.Rule
+import io.gitlab.arturbosch.detekt.api.Severity
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtLambdaArgument
+
+class ScreenAndDialogNamedArguments(config: Config) : Rule(config) {
+
+ override val issue =
+ Issue(
+ javaClass.simpleName,
+ Severity.CodeSmell,
+ "This rule reports Screen and Dialog composable calls that do not exclusively use named arguments",
+ Debt(mins = 1),
+ )
+
+ override fun visitCallExpression(expression: KtCallExpression) {
+ super.visitCallExpression(expression)
+ val name = expression.calleeExpression?.text ?: return
+
+ if (!isProbablyScreenOrDialog(name)) return
+
+ val args =
+ expression.valueArguments.let {
+ val skipLast = it.lastOrNull() is KtLambdaArgument
+ if (skipLast) it.dropLast(1) else it
+ }
+
+ val hasUnnamed = args.any { !it.isNamed() }
+ if (hasUnnamed) {
+ report(
+ CodeSmell(
+ issue = issue,
+ entity = Entity.from(element = expression.originalElement, offset = 0),
+ message = "Call to composable `$name` must use only named arguments.",
+ )
+ )
+ }
+ }
+
+ // We can't access the function declaration to see if this is a @Composable here.
+ private fun isProbablyScreenOrDialog(name: String): Boolean =
+ name[0].isUpperCase() && (name.endsWith("Screen") || name.endsWith("Dialog"))
+}
diff --git a/android/test/detekt/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider b/android/test/detekt/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider
new file mode 100644
index 0000000000..bfb5c29315
--- /dev/null
+++ b/android/test/detekt/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider
@@ -0,0 +1 @@
+net.mullvad.mullvadvpn.detekt.extensions.CustomProvider
diff --git a/android/test/detekt/src/main/resources/config/config.yml b/android/test/detekt/src/main/resources/config/config.yml
new file mode 100644
index 0000000000..e81f814ba1
--- /dev/null
+++ b/android/test/detekt/src/main/resources/config/config.yml
@@ -0,0 +1,4 @@
+custom:
+ ScreenAndDialogNamedArguments:
+ active: true
+ includes: ["**/net/mullvad/mullvadvpn/compose/**"]
diff --git a/android/test/detekt/src/test/kotlin/net/mullvad/mullvadvpn/detekt/extensions/ScreenAndDialogNamedArgumentsTest.kt b/android/test/detekt/src/test/kotlin/net/mullvad/mullvadvpn/detekt/extensions/ScreenAndDialogNamedArgumentsTest.kt
new file mode 100644
index 0000000000..fd7250ed6b
--- /dev/null
+++ b/android/test/detekt/src/test/kotlin/net/mullvad/mullvadvpn/detekt/extensions/ScreenAndDialogNamedArgumentsTest.kt
@@ -0,0 +1,98 @@
+package net.mullvad.mullvadvpn.detekt.extensions
+
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.test.lint
+import net.mullvad.mullvadvpn.detekt.extensions.rules.ScreenAndDialogNamedArguments
+import org.junit.jupiter.api.Test
+
+class ScreenAndDialogNamedArgumentsTest {
+
+ private val subject = ScreenAndDialogNamedArguments(Config.empty)
+
+ @Test
+ fun `it should find one call that doesn't use only named arguments`() {
+ val findings = subject.lint(incorrectCall)
+ assert(findings.size == 1)
+ }
+
+ @Test
+ fun `it should not report an error if all arguments are named`() {
+ val findings = subject.lint(correctCall)
+ assert(findings.isEmpty())
+ }
+
+ @Test
+ fun `it should ignore functions that do not end in Screen or Dialog`() {
+ val findings = subject.lint(ignoredCall)
+ assert(findings.isEmpty())
+ }
+
+ @Test
+ fun `it should ignore trailing lambda parameters`() {
+ val findings = subject.lint(trailingLambda)
+ assert(findings.isEmpty())
+ }
+}
+
+private val incorrectCall: String =
+ """
+ @Composable
+ fun ExampleComposeScreen(
+ arg1: Int,
+ arg2: String = "",
+ ) {}
+
+ @Composable
+ fun Caller() {
+ ExampleComposeScreen(2, args2 = "named")
+ }
+"""
+ .trimIndent()
+
+private val correctCall: String =
+ """
+ @Composable
+ fun ExampleComposeScreen(
+ arg1: Int,
+ arg2: String = "",
+ ) {}
+
+ @Composable
+ fun Caller() {
+ ExampleComposeScreen(arg1 = 2, args2 = "named")
+ }
+"""
+ .trimIndent()
+
+private val ignoredCall: String =
+ """
+ @Composable
+ fun ExampleComposable(
+ arg1: Int,
+ arg2: String = "",
+ ) {}
+
+ fun initScreen(arg: Int) {}
+
+ @Composable
+ fun Caller() {
+ ExampleComposable(2, args2 = "named")
+ initScreen(2)
+ }
+"""
+ .trimIndent()
+
+private val trailingLambda: String =
+ """
+ @Composable
+ fun TrailingLambdaDialog(arg: Int, callback: (Int) -> Unit) {
+ callback(arg)
+ }
+ @Composable
+ fun Caller() {
+ TrailingLambdaDialog(arg = 2) {
+ println(it)
+ }
+ }
+"""
+ .trimIndent()