Rewrite WifiPermissionsActivity to Compose (#640)

This commit is contained in:
Ricki Hirner 2024-03-11 16:23:25 +01:00 committed by GitHub
parent 06b4cf9477
commit 75a0c77b5f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 355 additions and 369 deletions

View file

@ -157,7 +157,7 @@
android:parentActivityName=".ui.account.AccountActivity2" />
<activity
android:name=".ui.account.WifiPermissionsActivity"
android:label="@string/wifi_permissions_label"
android:theme="@style/AppTheme.NoActionBar"
android:parentActivityName=".ui.account.SettingsActivity" />
<activity

View file

@ -16,6 +16,7 @@ object Constants {
val HOMEPAGE_URL = "https://www.davx5.com".toUri()
const val HOMEPAGE_PATH_FAQ = "faq"
const val HOMEPAGE_PATH_FAQ_SYNC_NOT_RUN = "synchronization-is-not-run-as-expected"
const val HOMEPAGE_PATH_FAQ_LOCATION_PERMISSION = "wifi-ssid-restriction-location-permission"
const val HOMEPAGE_PATH_OPEN_SOURCE = "donate"
const val HOMEPAGE_PATH_PRIVACY = "privacy"
const val HOMEPAGE_PATH_TESTED_SERVICES = "tested-with"

View file

@ -16,26 +16,21 @@ import androidx.activity.viewModels
import androidx.annotation.MainThread
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
@ -45,10 +40,9 @@ import at.bitfire.davdroid.PackageChangedReceiver
import at.bitfire.davdroid.R
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.ui.widget.CardWithImage
import at.bitfire.davdroid.ui.widget.PermissionSwitchRow
import at.bitfire.davdroid.util.PermissionUtils
import at.bitfire.ical4android.TaskProvider
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import java.util.logging.Level
class PermissionsActivity: AppCompatActivity() {
@ -149,82 +143,6 @@ fun PermissionsContent(model: PermissionsActivity.Model = viewModel()) {
}
}
@Composable
@OptIn(ExperimentalPermissionsApi::class)
fun PermissionSwitchRow(
text: String,
permissions: List<String>,
summaryWhenGranted: String,
summaryWhenNotGranted: String,
modifier: Modifier = Modifier,
fontWeight: FontWeight = FontWeight.Normal
) {
val state = rememberMultiplePermissionsState(permissions = permissions.toList())
PermissionSwitchRow(
text = text,
fontWeight = fontWeight,
summaryWhenGranted = summaryWhenGranted,
summaryWhenNotGranted = summaryWhenNotGranted,
allPermissionsGranted = state.allPermissionsGranted,
onLaunchRequest = state::launchMultiplePermissionRequest,
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun PermissionSwitchRow_Preview() {
PermissionSwitchRow(
text = "Contacts",
allPermissionsGranted = false,
summaryWhenGranted = "Granted",
summaryWhenNotGranted = "Not granted",
onLaunchRequest = {}
)
}
@Composable
fun PermissionSwitchRow(
text: String,
allPermissionsGranted: Boolean,
summaryWhenGranted: String,
summaryWhenNotGranted: String,
modifier: Modifier = Modifier,
fontWeight: FontWeight = FontWeight.Normal,
onLaunchRequest: () -> Unit
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = text,
modifier = Modifier.fillMaxWidth(),
fontWeight = fontWeight,
style = MaterialTheme.typography.body1
)
Text(
text = if (allPermissionsGranted) summaryWhenGranted else summaryWhenNotGranted,
modifier = Modifier.fillMaxWidth(),
style = MaterialTheme.typography.body2
)
}
Switch(
checked = allPermissionsGranted,
enabled = !allPermissionsGranted,
onCheckedChange = { checked ->
if (checked) {
onLaunchRequest()
}
}
)
}
}
@Composable
fun PermissionsCard(
keepPermissions: Boolean?,

View file

@ -11,26 +11,58 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.location.LocationManager
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.annotation.MainThread
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.Scaffold
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.CloudOff
import androidx.compose.material.icons.filled.Help
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.app.TaskStackBuilder
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.core.location.LocationManagerCompat
import androidx.core.text.HtmlCompat
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import at.bitfire.davdroid.Constants
import at.bitfire.davdroid.Constants.withStatParams
import at.bitfire.davdroid.R
import at.bitfire.davdroid.databinding.ActivityWifiPermissionsBinding
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.ui.AppTheme
import at.bitfire.davdroid.ui.widget.PermissionSwitchRow
import at.bitfire.davdroid.util.PermissionUtils
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@AndroidEntryPoint
class WifiPermissionsActivity: AppCompatActivity() {
companion object {
@ -44,48 +76,43 @@ class WifiPermissionsActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!PermissionUtils.WIFI_SSID_PERMISSIONS.all { perm -> PermissionUtils.declaresPermission(packageManager, perm) })
throw IllegalArgumentException("WiFi SSID restriction requires location permissions")
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val binding = ActivityWifiPermissionsBinding.inflate(layoutInflater)
binding.lifecycleOwner = this
binding.model = model
setContentView(binding.root)
model.needLocation.observe(this) { needPermission ->
if (needPermission && model.haveLocation.value == false)
ActivityCompat.requestPermissions(this, arrayOf(model.PERMISSION_LOCATION), 0)
}
model.haveBackgroundLocation.observe(this) { status ->
val label = if (Build.VERSION.SDK_INT >= 30)
packageManager.backgroundPermissionOptionLabel
else
getString(R.string.wifi_permissions_background_location_permission_label)
binding.backgroundLocationStatus.text = HtmlCompat.fromHtml(getString(
if (status) R.string.wifi_permissions_background_location_permission_on else R.string.wifi_permissions_background_location_permission_off,
label
), HtmlCompat.FROM_HTML_MODE_LEGACY)
}
model.needBackgroundLocation.observe(this) { needPermission ->
if (needPermission && model.haveBackgroundLocation.value == false)
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), 0)
}
binding.backgroundLocationDisclaimer.text = getString(R.string.wifi_permissions_background_location_disclaimer, getString(R.string.app_name))
binding.settingsBtn.setOnClickListener {
PermissionUtils.showAppSettings(this)
}
model.needLocationEnabled.observe(this) { needLocation ->
if (needLocation != null && needLocation != model.isLocationEnabled.value) {
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
if (intent.resolveActivity(packageManager) != null)
startActivity(intent)
else
Logger.log.warning("Couldn't resolve Location settings Intent")
setContent {
AppTheme {
Scaffold(
topBar = {
TopAppBar(
navigationIcon = {
IconButton(onClick = { onSupportNavigateUp() }) {
Icon(Icons.AutoMirrored.Default.ArrowBack, stringResource(R.string.navigate_up))
}
},
title = { Text(stringResource(R.string.wifi_permissions_label)) },
actions = {
val uriHandler = LocalUriHandler.current
IconButton(onClick = {
uriHandler.openUri(Constants.HOMEPAGE_URL.buildUpon()
.appendPath(Constants.HOMEPAGE_PATH_FAQ)
.appendPath(Constants.HOMEPAGE_PATH_FAQ_LOCATION_PERMISSION)
.withStatParams("WifiPermissionsActivity")
.build().toString())
}) {
Icon(Icons.Default.Help, stringResource(R.string.help))
}
}
)
}
) { padding ->
Box(modifier = Modifier.padding(padding)) {
Content(
backgroundPermissionOptionLabel =
if (Build.VERSION.SDK_INT >= 30)
packageManager.backgroundPermissionOptionLabel.toString()
else
stringResource(R.string.wifi_permissions_background_location_permission_label),
locationServiceEnabled = model.isLocationEnabled.observeAsState(false).value
)
}
}
}
}
}
@ -96,70 +123,169 @@ class WifiPermissionsActivity: AppCompatActivity() {
builder.editIntentAt(builder.intentCount - 1)?.putExtra(SettingsActivity.EXTRA_ACCOUNT, account)
}
override fun onResume() {
super.onResume()
model.checkPermissions()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
model.checkPermissions()
}
@Composable
fun Content(
backgroundPermissionOptionLabel: String,
locationServiceEnabled: Boolean
) {
Column(Modifier
.padding(8.dp)
.verticalScroll(rememberScrollState())) {
Text(
stringResource(R.string.wifi_permissions_intro),
style = MaterialTheme.typography.body1
)
class Model(app: Application): AndroidViewModel(app) {
val PERMISSION_LOCATION =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
Manifest.permission.ACCESS_FINE_LOCATION // since Android 10, fine location is required
else
Manifest.permission.ACCESS_COARSE_LOCATION // Android 8+: coarse location is enough
val haveLocation = MutableLiveData<Boolean>()
val needLocation = MutableLiveData<Boolean>()
val haveBackgroundLocation = MutableLiveData<Boolean>()
val needBackgroundLocation = MutableLiveData<Boolean>()
val isLocationEnabled = MutableLiveData<Boolean>()
val needLocationEnabled = MutableLiveData<Boolean>()
val locationModeWatcher = object: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
checkPermissions()
}
}
init {
app.registerReceiver(locationModeWatcher, IntentFilter(LocationManager.MODE_CHANGED_ACTION))
checkPermissions()
}
override fun onCleared() {
getApplication<Application>().unregisterReceiver(locationModeWatcher)
}
fun checkPermissions() {
// Android 8.1+: location permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
val location = ContextCompat.checkSelfPermission(getApplication(), PERMISSION_LOCATION) == PackageManager.PERMISSION_GRANTED
haveLocation.value = location
needLocation.value = location
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
LocationPermission(
modifier = Modifier.padding(top = 16.dp)
)
// Android 10+: background location permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
BackgroundLocationPermission(
backgroundPermissionOptionLabel = backgroundPermissionOptionLabel,
modifier = Modifier.padding(top = 16.dp)
)
// Android 9+: location service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
getApplication<Application>().getSystemService<LocationManager>()?.let { locationManager ->
val locationEnabled = LocationManagerCompat.isLocationEnabled(locationManager)
isLocationEnabled.value = locationEnabled
needLocationEnabled.value = locationEnabled
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
LocationService(
locationServiceEnabled = locationServiceEnabled,
modifier = Modifier.padding(top = 16.dp)
)
// If permissions have actively been denied
Text(
stringResource(R.string.permissions_app_settings_hint),
style = MaterialTheme.typography.body2,
modifier = Modifier.padding(top = 16.dp)
)
val context = LocalContext.current
OutlinedButton(
onClick = { PermissionUtils.showAppSettings(context) }
) {
Text(stringResource(R.string.permissions_app_settings).uppercase())
}
Divider(Modifier.padding(vertical = 16.dp))
// Disclaimer
Row {
Text(
stringResource(R.string.wifi_permissions_background_location_disclaimer, stringResource(R.string.app_name)),
style = MaterialTheme.typography.body2,
modifier = Modifier.weight(1f)
)
Icon(Icons.Default.CloudOff, null, modifier = Modifier.padding(8.dp))
}
}
}
@Composable
fun LocationPermission(
modifier: Modifier = Modifier
) {
val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
Manifest.permission.ACCESS_FINE_LOCATION // since Android 10, fine location is required
else
Manifest.permission.ACCESS_COARSE_LOCATION // Android 8+: coarse location is enough
PermissionSwitchRow(
text = stringResource(R.string.wifi_permissions_location_permission),
permissions = listOf(permission),
summaryWhenGranted = stringResource(R.string.wifi_permissions_location_permission_on),
summaryWhenNotGranted = stringResource(R.string.wifi_permissions_location_permission_off),
modifier = modifier
)
}
@RequiresApi(Build.VERSION_CODES.Q)
@Composable
fun BackgroundLocationPermission(
backgroundPermissionOptionLabel: String,
modifier: Modifier = Modifier
) {
PermissionSwitchRow(
text = stringResource(R.string.wifi_permissions_background_location_permission),
permissions = listOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
summaryWhenGranted = stringResource(R.string.wifi_permissions_background_location_permission_on, backgroundPermissionOptionLabel),
summaryWhenNotGranted = stringResource(R.string.wifi_permissions_background_location_permission_off, backgroundPermissionOptionLabel),
modifier = modifier
)
}
@Composable
fun LocationService(
locationServiceEnabled: Boolean,
modifier: Modifier = Modifier
) {
Row(modifier.fillMaxWidth()) {
Column(Modifier.weight(1f)) {
Text(
stringResource(R.string.wifi_permissions_location_enabled),
style = MaterialTheme.typography.body1
)
Text(
stringResource(
if (locationServiceEnabled)
R.string.wifi_permissions_location_enabled_on
else
R.string.wifi_permissions_location_enabled_off
),
style = MaterialTheme.typography.body2
)
}
Switch(
checked = locationServiceEnabled,
onCheckedChange = {
val intent = Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)
if (intent.resolveActivity(packageManager) != null)
startActivity(intent)
}
)
}
}
@Composable
@Preview
fun Content_Preview() {
Content(
backgroundPermissionOptionLabel = stringResource(R.string.wifi_permissions_background_location_permission_label),
locationServiceEnabled = true
)
}
@HiltViewModel
class Model @Inject constructor(
context: Application
): ViewModel() {
val isLocationEnabled: LiveData<Boolean> = object: LiveData<Boolean>() {
val locationChangedReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
update()
}
}
// Android 10+: background location permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val backgroundLocation = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED
haveBackgroundLocation.value = backgroundLocation
needBackgroundLocation.value = backgroundLocation
override fun onActive() {
context.registerReceiver(locationChangedReceiver, IntentFilter(LocationManager.MODE_CHANGED_ACTION))
update()
}
override fun onInactive() {
context.unregisterReceiver(locationChangedReceiver)
}
@MainThread
fun update() {
context.getSystemService<LocationManager>()?.let { locationManager ->
val locationEnabled = LocationManagerCompat.isLocationEnabled(locationManager)
value = locationEnabled
}
}
}

View file

@ -0,0 +1,117 @@
package at.bitfire.davdroid.ui.widget
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
@Composable
fun PermissionSwitchRow(
text: String,
allPermissionsGranted: Boolean,
summaryWhenGranted: String,
summaryWhenNotGranted: String,
modifier: Modifier = Modifier,
fontWeight: FontWeight = FontWeight.Normal,
onLaunchRequest: () -> Unit
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = text,
modifier = Modifier.fillMaxWidth(),
fontWeight = fontWeight,
style = MaterialTheme.typography.body1
)
Text(
text = if (allPermissionsGranted) summaryWhenGranted else summaryWhenNotGranted,
modifier = Modifier.fillMaxWidth(),
style = MaterialTheme.typography.body2
)
}
Switch(
checked = allPermissionsGranted,
enabled = !allPermissionsGranted,
onCheckedChange = { checked ->
if (checked) {
onLaunchRequest()
}
}
)
}
}
@Composable
@OptIn(ExperimentalPermissionsApi::class)
fun PermissionSwitchRow(
text: String,
permissions: List<String>,
summaryWhenGranted: String,
summaryWhenNotGranted: String,
modifier: Modifier = Modifier,
fontWeight: FontWeight = FontWeight.Normal
) {
if (LocalInspectionMode.current) {
// preview
PermissionSwitchRow(
text = text,
fontWeight = fontWeight,
summaryWhenGranted = summaryWhenGranted,
summaryWhenNotGranted = summaryWhenNotGranted,
allPermissionsGranted = false,
onLaunchRequest = {},
modifier = modifier
)
return
}
val state = rememberMultiplePermissionsState(permissions = permissions.toList())
PermissionSwitchRow(
text = text,
fontWeight = fontWeight,
summaryWhenGranted = summaryWhenGranted,
summaryWhenNotGranted = summaryWhenNotGranted,
allPermissionsGranted = state.allPermissionsGranted,
onLaunchRequest = state::launchMultiplePermissionRequest,
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun PermissionSwitchRow_Preview_NotGranted() {
PermissionSwitchRow(
text = "Contacts",
allPermissionsGranted = false,
summaryWhenGranted = "Granted",
summaryWhenNotGranted = "Not granted",
onLaunchRequest = {}
)
}
@Preview(showBackground = true)
@Composable
fun PermissionSwitchRow_Preview_Granted() {
PermissionSwitchRow(
text = "Contacts",
allPermissionsGranted = true,
summaryWhenGranted = "Granted",
summaryWhenNotGranted = "Not granted",
onLaunchRequest = {}
)
}

View file

@ -1,176 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.account.WifiPermissionsActivity">
<data>
<variable name="model" type="at.bitfire.davdroid.ui.account.WifiPermissionsActivity.Model" />
<import type="android.view.View" />
</data>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_margin">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="wrap_content"
android:layout_width="match_parent" >
<TextView
android:id="@+id/intro"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/wifi_permissions_intro"
android:textAlignment="viewStart"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/locationTitle"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/wifi_permissions_location_permission"
android:textAlignment="viewStart"
android:visibility="@{model.haveLocation != null ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toStartOf="@id/locationSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/intro" />
<TextView
android:id="@+id/locationStatus"
style="@style/TextAppearance.MaterialComponents.Body2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{model.haveLocation ? @string/wifi_permissions_location_permission_on : @string/wifi_permissions_location_permission_off}"
android:textAlignment="viewStart"
android:visibility="@{model.haveLocation != null ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toStartOf="@id/locationSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/locationTitle" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/locationSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/locationTitle"
app:layout_constraintBottom_toBottomOf="@id/locationStatus"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="@{model.haveLocation != null ? View.VISIBLE : View.GONE}"
android:clickable="@{!model.haveLocation}"
android:checked="@={model.needLocation}" />
<TextView
android:id="@+id/backgroundLocationTitle"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/card_margin_title_text"
android:text="@string/wifi_permissions_background_location_permission"
android:textAlignment="viewStart"
android:visibility="@{model.haveBackgroundLocation != null ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toStartOf="@id/backgroundLocationSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/locationStatus" />
<TextView
android:id="@+id/backgroundLocationStatus"
style="@style/TextAppearance.MaterialComponents.Body2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:visibility="@{model.haveBackgroundLocation != null ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toStartOf="@id/backgroundLocationSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/backgroundLocationTitle"
tools:text="@string/wifi_permissions_background_location_permission_off" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/backgroundLocationSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/backgroundLocationTitle"
app:layout_constraintBottom_toBottomOf="@id/backgroundLocationStatus"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="@{model.haveBackgroundLocation != null ? View.VISIBLE : View.GONE}"
android:enabled="@{model.haveLocation}"
android:clickable="@{!model.haveBackgroundLocation}"
android:checked="@={model.needBackgroundLocation}" />
<TextView
android:id="@+id/backgroundLocationDisclaimer"
app:drawableStartCompat="@drawable/ic_info"
android:drawablePadding="8dp"
style="@style/TextAppearance.MaterialComponents.Caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/wifi_permissions_background_location_disclaimer"
android:textAlignment="viewStart"
android:visibility="@{model.haveBackgroundLocation != null ? View.VISIBLE : View.GONE}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/backgroundLocationStatus" />
<TextView
android:id="@+id/locationEnabledTitle"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/wifi_permissions_location_enabled"
android:textAlignment="viewStart"
android:visibility="@{model.isLocationEnabled != null ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toStartOf="@id/locationEnabledSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/backgroundLocationDisclaimer" />
<TextView
android:id="@+id/locationEnabledStatus"
style="@style/TextAppearance.MaterialComponents.Body2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{model.isLocationEnabled ? @string/wifi_permissions_location_enabled_on : @string/wifi_permissions_location_enabled_off}"
android:textAlignment="viewStart"
android:visibility="@{model.isLocationEnabled != null ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toStartOf="@id/locationEnabledSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/locationEnabledTitle" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/locationEnabledSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@id/locationEnabledTitle"
app:layout_constraintBottom_toBottomOf="@id/locationEnabledStatus"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="@{model.isLocationEnabled != null ? View.VISIBLE : View.GONE}"
android:checked="@={model.needLocationEnabled}" />
<TextView
android:id="@+id/settingsHint"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/permissions_app_settings_hint"
android:textAlignment="viewStart"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/locationEnabledStatus" />
<Button
android:id="@+id/settingsBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:layout_constraintTop_toBottomOf="@id/settingsHint"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"
android:text="@string/permissions_app_settings"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</layout>

View file

@ -99,8 +99,8 @@
<string name="wifi_permissions_location_permission_off">Location permission denied</string>
<string name="wifi_permissions_background_location_permission">Background location permission</string>
<string name="wifi_permissions_background_location_permission_label">Allow all the time</string>
<string name="wifi_permissions_background_location_permission_on"><![CDATA[Location permission set to <b>%s</b>]]></string>
<string name="wifi_permissions_background_location_permission_off"><![CDATA[Location permission not set to <b>%s</b>]]></string>
<string name="wifi_permissions_background_location_permission_on">Location permission set to: %s</string>
<string name="wifi_permissions_background_location_permission_off">Location permission not set to: %s</string>
<string name="wifi_permissions_background_location_disclaimer">%s uses the Location permission only to determine the current WiFi\'s SSID for SSID-restricted accounts. This will happen even when the app is in background. No location data are collected, stored, processed or sent anywhere.</string>
<string name="wifi_permissions_location_enabled">Location always enabled</string>
<string name="wifi_permissions_location_enabled_on">Location service is enabled</string>