chore(android): Run spotlessApply with new version 7 (#7949)

Spotless version 7 introduced some new linter rules that need to be
applied for the kotlin static analysis checks to succeed.

Supersedes: #7929

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Jamil
2025-01-29 22:16:09 +00:00
committed by GitHub
parent 743d4937b2
commit 0222c25ae4
24 changed files with 149 additions and 132 deletions

View File

@@ -6,7 +6,7 @@ plugins {
id("com.google.dagger.hilt.android")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("com.diffplug.spotless") version "6.25.0"
id("com.diffplug.spotless") version "7.0.2"
id("com.google.firebase.appdistribution")
id("kotlin-parcelize")
id("androidx.navigation.safeargs")

View File

@@ -11,7 +11,5 @@ class HiltTestRunner : AndroidJUnitRunner() {
cl: ClassLoader?,
className: String?,
context: Context?,
): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
): Application = super.newApplication(cl, HiltTestApplication::class.java.name, context)
}

View File

@@ -46,7 +46,8 @@ fun waitForView(
uiController.loopMainThreadForAtLeast(100)
} while (System.currentTimeMillis() < endTime)
throw PerformException.Builder()
throw PerformException
.Builder()
.withCause(TimeoutException())
.withActionDescription(this.description)
.withViewDescription(HumanReadables.describe(rootView))

View File

@@ -15,7 +15,8 @@ internal class BaseUrlInterceptor(
val newUrl = BuildConfig.AUTH_BASE_URL.toHttpUrlOrNull()
val newRequest =
originalRequest.newBuilder()
originalRequest
.newBuilder()
.url(newUrl!!)
.build()
return chain.proceed(newRequest)

View File

@@ -31,29 +31,27 @@ enum class ResourceState {
UNSET,
}
fun ResourceState.isEnabled(): Boolean {
return this == ResourceState.ENABLED
}
fun ResourceState.isEnabled(): Boolean = this == ResourceState.ENABLED
fun ResourceState.stateSymbol(): String {
return if (this.isEnabled()) {
fun ResourceState.stateSymbol(): String =
if (this.isEnabled()) {
ON_SYMBOL
} else {
OFF_SYMBOL
}
}
fun ResourceState.toggle(): ResourceState {
return if (this.isEnabled()) {
fun ResourceState.toggle(): ResourceState =
if (this.isEnabled()) {
ResourceState.DISABLED
} else {
ResourceState.ENABLED
}
}
// Wrapper class used because `MutableStateFlow` will not
// notify subscribers if you submit the same object that's already in it.
class Favorites(val inner: HashSet<String>)
class Favorites(
val inner: HashSet<String>,
)
internal class Repository
@Inject
@@ -69,8 +67,8 @@ internal class Repository
MutableStateFlow(Favorites(HashSet(sharedPreferences.getStringSet(FAVORITE_RESOURCES_KEY, null).orEmpty())))
val favorites = _favorites.asStateFlow()
fun getConfigSync(): Config {
return Config(
fun getConfigSync(): Config =
Config(
sharedPreferences.getString(AUTH_BASE_URL_KEY, null)
?: BuildConfig.AUTH_BASE_URL,
sharedPreferences.getString(API_URL_KEY, null)
@@ -78,7 +76,6 @@ internal class Repository
sharedPreferences.getString(LOG_FILTER_KEY, null)
?: BuildConfig.LOG_FILTER,
)
}
fun getConfig(): Flow<Config> =
flow {
@@ -165,7 +162,9 @@ internal class Repository
}
fun saveInternetResourceStateSync(value: ResourceState): Unit =
sharedPreferences.edit().putString(ENABLED_INTERNET_RESOURCE_KEY, Gson().toJson(value))
sharedPreferences
.edit()
.putString(ENABLED_INTERNET_RESOURCE_KEY, Gson().toJson(value))
.apply()
fun saveNonce(value: String): Flow<Unit> =

View File

@@ -28,7 +28,8 @@ object AppModule {
EncryptedSharedPreferences.create(
app.applicationContext,
ENCRYPTED_SHARED_PREFERENCES,
MasterKey.Builder(app.applicationContext)
MasterKey
.Builder(app.applicationContext)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build(),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,

View File

@@ -37,7 +37,8 @@ internal object NetworkModule {
fun provideOkHttpClient(
baseUrlInterceptor: BaseUrlInterceptor,
loggingInterceptor: HttpLoggingInterceptor,
) = OkHttpClient.Builder()
) = OkHttpClient
.Builder()
.followRedirects(true)
.followSslRedirects(true)
.readTimeout(NETWORK_TIMEOUT, TimeUnit.SECONDS)
@@ -53,7 +54,8 @@ internal object NetworkModule {
okHttpClient: OkHttpClient,
moshi: Moshi,
): Retrofit =
Retrofit.Builder()
Retrofit
.Builder()
.baseUrl("http://localhost.com/")
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create(moshi))

View File

@@ -59,15 +59,15 @@ class AuthActivity : AppCompatActivity(R.layout.activity_auth) {
}
private fun showError() {
AlertDialog.Builder(this)
AlertDialog
.Builder(this)
.setTitle(R.string.error_dialog_title)
.setMessage(R.string.error_dialog_message)
.setPositiveButton(
R.string.error_dialog_button_text,
) { _, _ ->
this@AuthActivity.finish()
}
.setIcon(R.drawable.ic_firezone_logo)
}.setIcon(R.drawable.ic_firezone_logo)
.show()
}
}

View File

@@ -49,7 +49,9 @@ internal class AuthViewModel
}
internal sealed class ViewAction {
data class LaunchAuthFlow(val url: String) : ViewAction()
data class LaunchAuthFlow(
val url: String,
) : ViewAction()
object NavigateToSignIn : ViewAction()

View File

@@ -34,7 +34,8 @@ object CustomUriNotification {
manager.createNotificationChannel(chan)
val notificationBuilder =
NotificationCompat.Builder(context, CHANNEL_ID)
NotificationCompat
.Builder(context, CHANNEL_ID)
.setContentIntent(configIntent(context))
return status.applySettings(notificationBuilder)
}
@@ -50,7 +51,9 @@ object CustomUriNotification {
)
}
data class Error(val message: String) : StatusType() {
data class Error(
val message: String,
) : StatusType() {
override fun applySettings(builder: NotificationCompat.Builder) =
builder.apply {
setSmallIcon(R.drawable.ic_firezone_logo)

View File

@@ -78,7 +78,9 @@ internal class CustomUriViewModel
internal sealed class ViewAction {
data object AuthFlowComplete : ViewAction()
data class AuthFlowError(val errors: Iterable<String>) : ViewAction() {
data class AuthFlowError(
val errors: Iterable<String>,
) : ViewAction() {
constructor(vararg errors: String) : this(errors.toList())
}
}

View File

@@ -36,9 +36,7 @@ class ResourceDetailsBottomSheet(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
return inflater.inflate(R.layout.fragment_resource_details, container, false)
}
): View? = inflater.inflate(R.layout.fragment_resource_details, container, false)
override fun onViewCreated(
view: View,
@@ -92,13 +90,12 @@ class ResourceDetailsBottomSheet(
}
}
private fun resourceToggleText(resource: ResourceViewModel): String {
return if (resource.state.isEnabled()) {
private fun resourceToggleText(resource: ResourceViewModel): String =
if (resource.state.isEnabled()) {
"Disable this resource"
} else {
"Enable this resource"
}
}
private fun resourceHeader() {
if (resource.isInternetResource()) {

View File

@@ -9,7 +9,10 @@ import dev.firezone.android.tunnel.model.Site
import dev.firezone.android.tunnel.model.StatusEnum
import dev.firezone.android.tunnel.model.isInternetResource
class ResourceViewModel(resource: Resource, resourceState: ResourceState) {
class ResourceViewModel(
resource: Resource,
resourceState: ResourceState,
) {
val id: String = resource.id
val type: ResourceType = resource.type
val address: String? = resource.address
@@ -24,21 +27,16 @@ class ResourceViewModel(resource: Resource, resourceState: ResourceState) {
fun displayName(
resource: Resource,
state: ResourceState,
): String {
return if (resource.isInternetResource()) {
): String =
if (resource.isInternetResource()) {
internetResourceDisplayName(resource, state)
} else {
resource.name
}
}
fun internetResourceDisplayName(
resource: Resource,
state: ResourceState,
): String {
return "${state.stateSymbol()} ${resource.name}"
}
): String = "${state.stateSymbol()} ${resource.name}"
fun ResourceViewModel.isInternetResource(): Boolean {
return this.type == ResourceType.Internet
}
fun ResourceViewModel.isInternetResource(): Boolean = this.type == ResourceType.Internet

View File

@@ -11,8 +11,9 @@ import androidx.recyclerview.widget.RecyclerView
import dev.firezone.android.core.data.ResourceState
import dev.firezone.android.databinding.ListItemResourceBinding
internal class ResourcesAdapter(private val internetResourceToggle: () -> ResourceState) :
ListAdapter<ResourceViewModel, ResourcesAdapter.ViewHolder>(
internal class ResourcesAdapter(
private val internetResourceToggle: () -> ResourceState,
) : ListAdapter<ResourceViewModel, ResourcesAdapter.ViewHolder>(
ResourceDiffCallback(),
) {
override fun onCreateViewHolder(
@@ -38,7 +39,9 @@ internal class ResourcesAdapter(private val internetResourceToggle: () -> Resour
}
}
class ViewHolder(private val binding: ListItemResourceBinding) : RecyclerView.ViewHolder(binding.root) {
class ViewHolder(
private val binding: ListItemResourceBinding,
) : RecyclerView.ViewHolder(binding.root) {
fun bind(resource: ResourceViewModel) {
binding.resourceNameText.text = resource.displayName
if (resource.isInternetResource()) {
@@ -53,15 +56,11 @@ internal class ResourcesAdapter(private val internetResourceToggle: () -> Resour
override fun areItemsTheSame(
oldItem: ResourceViewModel,
newItem: ResourceViewModel,
): Boolean {
return oldItem.id == newItem.id
}
): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: ResourceViewModel,
newItem: ResourceViewModel,
): Boolean {
return oldItem == newItem
}
): Boolean = oldItem == newItem
}
}

View File

@@ -75,9 +75,7 @@ class SessionActivity : AppCompatActivity() {
super.onDestroy()
}
fun internetState(): ResourceState {
return tunnelService?.internetState() ?: ResourceState.UNSET
}
fun internetState(): ResourceState = tunnelService?.internetState() ?: ResourceState.UNSET
private fun onInternetResourceToggled(): ResourceState {
tunnelService?.let {

View File

@@ -58,17 +58,24 @@ internal class SessionViewModel
}
}
return if (repo.favorites.value.inner.isEmpty()) {
return if (repo.favorites.value.inner
.isEmpty()
) {
resources
} else if (selectedTab == RESOURCES_TAB_FAVORITES) {
resources.filter { repo.favorites.value.inner.contains(it.id) }
resources.filter {
repo.favorites.value.inner
.contains(it.id)
}
} else {
resources
}
}
fun forceTab(): Int? =
if (repo.favorites.value.inner.isEmpty()) {
if (repo.favorites.value.inner
.isEmpty()
) {
RESOURCES_TAB_ALL
} else {
null
@@ -78,10 +85,14 @@ internal class SessionViewModel
selectedTab = position
}
fun isFavorite(id: String) = repo.favorites.value.inner.contains(id)
fun isFavorite(id: String) =
repo.favorites.value.inner
.contains(id)
fun tabLayoutVisibility(): Int =
if (repo.favorites.value.inner.isNotEmpty()) {
if (repo.favorites.value.inner
.isNotEmpty()
) {
View.VISIBLE
} else {
View.GONE

View File

@@ -108,16 +108,16 @@ internal class SettingsActivity : AppCompatActivity() {
}
}
private inner class SettingsPagerAdapter(activity: FragmentActivity) :
FragmentStateAdapter(activity) {
private inner class SettingsPagerAdapter(
activity: FragmentActivity,
) : FragmentStateAdapter(activity) {
override fun getItemCount(): Int = 2 // Two tabs
override fun createFragment(position: Int): Fragment {
return when (position) {
override fun createFragment(position: Int): Fragment =
when (position) {
0 -> AdvancedSettingsFragment()
1 -> LogSettingsFragment()
else -> throw IllegalArgumentException("Invalid tab position: $position")
}
}
}
}

View File

@@ -56,7 +56,12 @@ internal class SettingsViewModel
fun onViewResume(context: Context) {
val directory = File(context.cacheDir.absolutePath + "/logs")
val totalSize = directory.walkTopDown().filter { it.isFile }.map { it.length() }.sum()
val totalSize =
directory
.walkTopDown()
.filter { it.isFile }
.map { it.length() }
.sum()
_uiState.value =
_uiState.value.copy(
@@ -198,14 +203,13 @@ internal class SettingsViewModel
config.logFilter.isNotBlank()
}
private fun isUriValid(uri: String): Boolean {
return try {
private fun isUriValid(uri: String): Boolean =
try {
URI(uri)
true
} catch (e: URISyntaxException) {
false
}
}
internal data class UiState(
val isSaveButtonEnabled: Boolean = false,

View File

@@ -48,9 +48,7 @@ internal class SplashViewModel
}
}
private fun hasVpnPermissions(context: Context): Boolean {
return android.net.VpnService.prepare(context) == null
}
private fun hasVpnPermissions(context: Context): Boolean = android.net.VpnService.prepare(context) == null
internal sealed class ViewAction {
object NavigateToVpnPermission : ViewAction()

View File

@@ -10,7 +10,9 @@ import dev.firezone.android.tunnel.TunnelService
// None of the TunnelService lifecycle callbacks are called when a user disconnects the VPN
// from the system settings. This class listens for network changes and shuts down the service
// when the network is lost, which achieves the same effect.
class DisconnectMonitor(private val tunnelService: TunnelService) : ConnectivityManager.NetworkCallback() {
class DisconnectMonitor(
private val tunnelService: TunnelService,
) : ConnectivityManager.NetworkCallback() {
private var vpnNetwork: Network? = null
// This handler is used to stop connlib when the VPN fd is lost

View File

@@ -10,7 +10,9 @@ import dev.firezone.android.tunnel.TunnelService
import dev.firezone.android.tunnel.TunnelStatusNotification
import java.net.InetAddress
class NetworkMonitor(private val tunnelService: TunnelService) : ConnectivityManager.NetworkCallback() {
class NetworkMonitor(
private val tunnelService: TunnelService,
) : ConnectivityManager.NetworkCallback() {
private var lastNetwork: Network? = null
private var lastDns: List<InetAddress>? = null

View File

@@ -101,9 +101,7 @@ class TunnelService : VpnService() {
fun getService(): TunnelService = this@TunnelService
}
override fun onBind(intent: Intent): IBinder {
return binder
}
override fun onBind(intent: Intent): IBinder = binder
private val callback: ConnlibCallback =
object : ConnlibCallback {
@@ -168,48 +166,51 @@ class TunnelService : VpnService() {
}
}
Builder().apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setMetered(false) // Inherit the metered status from the underlying networks.
Builder()
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setMetered(false) // Inherit the metered status from the underlying networks.
}
if (tunnelRoutes.all { it.prefix != 0 }) {
// Allow traffic to bypass the VPN interface when Always-on VPN is enabled only
// if full-route is not enabled.
allowBypass()
}
setUnderlyingNetworks(null) // Use all available networks.
setSession(SESSION_NAME)
setMtu(MTU)
handleApplications(appRestrictions, "allowedApplications") { addAllowedApplication(it) }
handleApplications(
appRestrictions,
"disallowedApplications",
) { addDisallowedApplication(it) }
// Never route GCM notifications through the tunnel.
addDisallowedApplication("com.google.android.gms") // Google Mobile Services
addDisallowedApplication("com.google.firebase.messaging") // Firebase Cloud Messaging
addDisallowedApplication("com.google.android.gsf") // Google Services Framework
tunnelRoutes.forEach {
addRoute(it.address, it.prefix)
}
tunnelDnsAddresses.forEach { dns ->
addDnsServer(dns)
}
addAddress(tunnelIpv4Address!!, 32)
addAddress(tunnelIpv6Address!!, 128)
}.establish()
?.detachFd()
?.also { fd ->
connlibSessionPtr?.let {
ConnlibSession.setTun(it, fd)
}
}
if (tunnelRoutes.all { it.prefix != 0 }) {
// Allow traffic to bypass the VPN interface when Always-on VPN is enabled only
// if full-route is not enabled.
allowBypass()
}
setUnderlyingNetworks(null) // Use all available networks.
setSession(SESSION_NAME)
setMtu(MTU)
handleApplications(appRestrictions, "allowedApplications") { addAllowedApplication(it) }
handleApplications(
appRestrictions,
"disallowedApplications",
) { addDisallowedApplication(it) }
// Never route GCM notifications through the tunnel.
addDisallowedApplication("com.google.android.gms") // Google Mobile Services
addDisallowedApplication("com.google.firebase.messaging") // Firebase Cloud Messaging
addDisallowedApplication("com.google.android.gsf") // Google Services Framework
tunnelRoutes.forEach {
addRoute(it.address, it.prefix)
}
tunnelDnsAddresses.forEach { dns ->
addDnsServer(dns)
}
addAddress(tunnelIpv4Address!!, 32)
addAddress(tunnelIpv6Address!!, 128)
}.establish()?.detachFd()?.also { fd ->
connlibSessionPtr?.let {
ConnlibSession.setTun(it, fd)
}
}
}
private val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED)
@@ -263,13 +264,9 @@ class TunnelService : VpnService() {
super.onRevoke()
}
fun internetState(): ResourceState {
return resourceState
}
fun internetState(): ResourceState = resourceState
private fun internetResource(): Resource? {
return tunnelResources.firstOrNull { it.isInternetResource() }
}
private fun internetResource(): Resource? = tunnelResources.firstOrNull { it.isInternetResource() }
// UI updates for resources
fun resourcesUpdated() {
@@ -432,7 +429,10 @@ class TunnelService : VpnService() {
// Get the deviceId from the preferenceRepository, or save a new UUIDv4 and return that if it doesn't exist
val deviceId =
repo.getDeviceIdSync() ?: run {
val newDeviceId = java.util.UUID.randomUUID().toString()
val newDeviceId =
java.util.UUID
.randomUUID()
.toString()
repo.saveDeviceIdSync(newDeviceId)
newDeviceId
}

View File

@@ -36,7 +36,8 @@ object TunnelStatusNotification {
manager.createNotificationChannel(chan)
val notificationBuilder =
NotificationCompat.Builder(context, CHANNEL_ID)
NotificationCompat
.Builder(context, CHANNEL_ID)
.setContentIntent(configIntent(context))
return status.applySettings(notificationBuilder)
}

View File

@@ -18,9 +18,7 @@ data class Resource(
val status: StatusEnum,
) : Parcelable
fun Resource.isInternetResource(): Boolean {
return this.type == ResourceType.Internet
}
fun Resource.isInternetResource(): Boolean = this.type == ResourceType.Internet
enum class ResourceType {
@Json(name = "dns")