Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix all baselined lint issues #6921

Merged
merged 23 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ android {

lint {
lintConfig = file("${rootProject.projectDir}/config/lint.xml")
baseline = file("lint-baseline.xml")
abortOnError = true
warningsAsErrors = true
checkDependencies = true
}
}

Expand Down
37 changes: 0 additions & 37 deletions android/app/lint-baseline.xml

This file was deleted.

2 changes: 1 addition & 1 deletion android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
android:theme="@style/Theme.App.Starting"
android:extractNativeLibs="true"
android:allowBackup="false"
android:banner="@drawable/banner"
android:banner="@mipmap/ic_banner"
android:name=".MullvadApplication"
tools:ignore="DataExtractionRules,GoogleAppIndexingWarning"/>
</manifest>
10 changes: 8 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<!-- Suppress warning, just using queries tag is not enough for our all, we need access to all
packages to allow the user to select apps for split tunneling -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- https://developer.android.com/guide/components/fg-service-types#system-exempted -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
Expand All @@ -20,9 +23,12 @@
android:required="false" />
<uses-feature android:glEsVersion="0x00020000"
android:required="false" />

<application android:name=".MullvadApplication"
android:banner="@mipmap/ic_banner"
android:allowBackup="false"
android:banner="@drawable/banner"
android:fullBackupContent="@xml/full_backup_content"
android:dataExtractionRules="@xml/data_extraction_rules"
android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -118,23 +119,13 @@ private fun Notification(notificationBannerData: NotificationData) {
.testTag(NOTIFICATION_BANNER)
) {
val (status, textTitle, textMessage, actionIcon) = createRefs()
Box(
modifier =
Modifier.background(
color =
when (statusLevel) {
StatusLevel.Error -> MaterialTheme.colorScheme.error
StatusLevel.Warning -> MaterialTheme.colorScheme.warning
StatusLevel.Info -> MaterialTheme.colorScheme.surfaceContainer
},
shape = CircleShape,
)
.size(Dimens.notificationStatusIconSize)
.constrainAs(status) {
top.linkTo(textTitle.top)
start.linkTo(parent.start)
bottom.linkTo(textTitle.bottom)
}
NotificationDot(
statusLevel,
Modifier.constrainAs(status) {
top.linkTo(textTitle.top)
start.linkTo(parent.start)
bottom.linkTo(textTitle.bottom)
},
)
Text(
text = title.uppercase(),
Expand Down Expand Up @@ -173,24 +164,58 @@ private fun Notification(notificationBannerData: NotificationData) {
)
}
action?.let {
IconButton(
NotificationAction(
it.icon,
onClick = it.onClick,
contentDescription = it.contentDescription,
modifier =
Modifier.constrainAs(actionIcon) {
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
.testTag(NOTIFICATION_BANNER_ACTION)
.padding(all = Dimens.notificationEndIconPadding),
onClick = it.onClick,
) {
Icon(
modifier = Modifier.padding(Dimens.notificationIconPadding),
imageVector = it.icon,
contentDescription = it.contentDescription,
tint = MaterialTheme.colorScheme.onSurface,
)
}
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
},
)
}
}
}

@Composable
private fun NotificationDot(statusLevel: StatusLevel, modifier: Modifier) {
Box(
modifier =
modifier
.background(
color =
when (statusLevel) {
StatusLevel.Error -> MaterialTheme.colorScheme.error
StatusLevel.Warning -> MaterialTheme.colorScheme.warning
StatusLevel.Info -> MaterialTheme.colorScheme.surfaceContainer
},
shape = CircleShape,
)
.size(Dimens.notificationStatusIconSize)
)
}

@Composable
private fun NotificationAction(
imageVector: ImageVector,
contentDescription: String?,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
IconButton(
modifier =
modifier
.testTag(NOTIFICATION_BANNER_ACTION)
.padding(all = Dimens.notificationEndIconPadding),
onClick = onClick,
) {
Icon(
modifier = Modifier.padding(Dimens.notificationIconPadding),
imageVector = imageVector,
contentDescription = contentDescription,
tint = MaterialTheme.colorScheme.onSurface,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import net.mullvad.mullvadvpn.compose.textfield.CustomTextField
import net.mullvad.mullvadvpn.compose.util.MAX_VOUCHER_LENGTH
import net.mullvad.mullvadvpn.compose.util.vouchersVisualTransformation
import net.mullvad.mullvadvpn.constant.VOUCHER_LENGTH
import net.mullvad.mullvadvpn.lib.model.DAYS_PER_VOUCHER_MONTH
import net.mullvad.mullvadvpn.lib.model.RedeemVoucherError
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
Expand Down Expand Up @@ -162,18 +163,18 @@ fun RedeemVoucherDialog(
val message =
stringResource(
R.string.added_to_your_account,
when (days) {
0 -> {
when {
days == 0 -> {
stringResource(R.string.less_than_one_day)
}
in 1..59 -> {
days < 2 * DAYS_PER_VOUCHER_MONTH -> {
pluralStringResource(id = R.plurals.days, count = days, days)
}
else -> {
pluralStringResource(
id = R.plurals.months,
count = days / 30,
days / 30,
count = days / DAYS_PER_VOUCHER_MONTH,
days / DAYS_PER_VOUCHER_MONTH,
)
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ package net.mullvad.mullvadvpn.compose.extensions

import android.content.res.Resources
import net.mullvad.mullvadvpn.R
import org.joda.time.DateTime
import org.joda.time.Duration
import org.joda.time.Period

private const val DAYS_IN_STANDARD_YEAR = 365

fun Resources.getExpiryQuantityString(accountExpiry: Duration): String {
val expiryPeriod = Period(DateTime.now(), accountExpiry)
val days = accountExpiry.standardDays.toInt()
val years = (accountExpiry.standardDays / DAYS_IN_STANDARD_YEAR).toInt()

return if (accountExpiry.millis <= 0) {
getString(R.string.out_of_time)
} else if (expiryPeriod.years > 0) {
getRemainingText(this, R.plurals.years_left, expiryPeriod.years)
} else if (expiryPeriod.months >= 3) {
getRemainingText(this, R.plurals.months_left, expiryPeriod.months)
} else if (expiryPeriod.months > 0 || expiryPeriod.days >= 1) {
getRemainingText(this, R.plurals.days_left, expiryPeriod.days)
} else if (years > 1) {
getRemainingText(this, R.plurals.years_left, years)
} else if (days >= 1) {
getRemainingText(this, R.plurals.days_left, days)
} else {
getString(R.string.less_than_a_day_left)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ private fun PreviewLoginScreen(
AppTheme { LoginScreen(state = state) }
}

private const val TOP_SPACER_WEIGHT = 1f
private const val BOTTOM_SPACER_WEIGHT = 3f

@Destination<RootGraph>(style = LoginTransition::class)
@Composable
fun Login(
Expand Down Expand Up @@ -177,15 +180,15 @@ private fun LoginScreen(
.background(MaterialTheme.colorScheme.primary)
.verticalScroll(scrollState)
) {
Spacer(modifier = Modifier.weight(1f))
Spacer(modifier = Modifier.weight(TOP_SPACER_WEIGHT))
LoginIcon(
state.loginState,
modifier =
Modifier.align(Alignment.CenterHorizontally)
.padding(bottom = Dimens.largePadding),
)
LoginContent(state, onAccountNumberChange, onLoginClick, onDeleteHistoryClick)
Spacer(modifier = Modifier.weight(3f))
Spacer(modifier = Modifier.weight(BOTTOM_SPACER_WEIGHT))
CreateAccountPanel(onCreateAccountClick, isEnabled = state.loginState is Idle)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand All @@ -23,8 +22,6 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.constant.EMPTY_STRING
import net.mullvad.mullvadvpn.constant.NEWLINE_STRING

Expand Down Expand Up @@ -53,9 +50,6 @@ fun CustomTextField(
imeAction = ImeAction.Done,
),
) {

val scope = rememberCoroutineScope()

// This is the same implementation as in BasicTextField.kt but with initial selection set at the
// end of the text rather than in the beginning.
// This is a fix for https://issuetracker.google.com/issues/272693535.
Expand Down Expand Up @@ -97,16 +91,7 @@ fun CustomTextField(
singleLine = true,
placeholder = placeholderText?.let { { Text(text = it) } },
keyboardOptions = keyboardOptions,
keyboardActions =
KeyboardActions(
onDone = {
scope.launch {
// https://issuetracker.google.com/issues/305518328
delay(100)
onSubmit(value)
}
}
),
keyboardActions = KeyboardActions(onDone = { onSubmit(value) }),
visualTransformation = visualTransformation,
colors = colors,
isError = !isValidValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import net.mullvad.mullvadvpn.repository.ApiAccessRepository
import net.mullvad.mullvadvpn.util.delayAtLeast
import org.apache.commons.validator.routines.InetAddressValidator

@Suppress("TooManyFunctions")
class EditApiAccessMethodViewModel(
private val apiAccessRepository: ApiAccessRepository,
private val inetAddressValidator: InetAddressValidator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase
import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase
import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase

@Suppress("TooManyFunctions")
class SelectLocationViewModel(
private val relayListFilterRepository: RelayListFilterRepository,
private val availableProvidersUseCase: AvailableProvidersUseCase,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sealed interface VpnSettingsSideEffect {
data object NavigateToDnsDialog : VpnSettingsSideEffect
}

@Suppress("TooManyFunctions")
class VpnSettingsViewModel(
private val repository: SettingsRepository,
private val relayListRepository: RelayListRepository,
Expand Down
21 changes: 21 additions & 0 deletions android/app/src/main/res/xml/data_extraction_rules.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<exclude domain="root" />
<exclude domain="file" />
<exclude domain="database" />
<exclude domain="sharedpref" />
<exclude domain="external" />
</cloud-backup>
<device-transfer>
<exclude domain="root" />
<exclude domain="file" />
<exclude domain="database" />
<exclude domain="sharedpref" />
<exclude domain="external" />
</device-transfer>
</data-extraction-rules>
16 changes: 16 additions & 0 deletions android/app/src/main/res/xml/full_backup_content.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?><!--
Full backup content file
See https://developer.android.com/guide/topics/manifest/application-element#fullBackupContent
for details.
-->
<full-backup-content>
<exclude domain="file" />
<exclude domain="database" />
<exclude domain="sharedpref" />
<exclude domain="external" />
<exclude domain="root" />
<exclude domain="device_file" />
<exclude domain="device_database" />
<exclude domain="device_sharedpref" />
<exclude domain="device_root" />
</full-backup-content>
Loading
Loading