diff options
| author | David Göransson <david.goransson@mullvad.net> | 2025-07-28 14:38:49 +0200 |
|---|---|---|
| committer | David Göransson <david.goransson@mullvad.net> | 2025-07-28 14:38:49 +0200 |
| commit | 4467d98ce03bc3057f68dc19ad17b71c44eb3501 (patch) | |
| tree | c25463ab47568fb73727646c2ce4d0414c6f7bcd | |
| parent | e2d91ff3d404d17a66c925bc5cd22dc29417550b (diff) | |
| parent | 235c1446b096d40e6ee686878391732a41c0fefb (diff) | |
| download | mullvadvpn-4467d98ce03bc3057f68dc19ad17b71c44eb3501.tar.xz mullvadvpn-4467d98ce03bc3057f68dc19ad17b71c44eb3501.zip | |
Merge branch 'detekt-named-args-droid-1528'
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() |
