mirror of
https://github.com/bitfireAT/davx5-ose
synced 2024-07-22 03:01:24 +00:00
Rewrite PermissionsIntroPage to M3 (#758)
* Migrated to M3 Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Replaced preview theme Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Fixed theme Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Forced all sets to be private Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Moved Composables and Model to individual files Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Fixed naming Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Theme / M3 changes * Observe lifecycle from within Screen * Minor changes --------- Signed-off-by: Arnau Mora <arnyminerz@proton.me> Co-authored-by: Ricki Hirner <hirner@bitfire.at>
This commit is contained in:
parent
e6eb90861e
commit
4cffbe7b40
|
@ -4,273 +4,22 @@
|
|||
|
||||
package at.bitfire.davdroid.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.MainThread
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
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.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
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.viewModelScope
|
||||
import at.bitfire.davdroid.BuildConfig
|
||||
import at.bitfire.davdroid.R
|
||||
import at.bitfire.davdroid.log.Logger
|
||||
import at.bitfire.davdroid.ui.composable.BasicTopAppBar
|
||||
import at.bitfire.davdroid.ui.composable.CardWithImage
|
||||
import at.bitfire.davdroid.ui.composable.PermissionSwitchRow
|
||||
import at.bitfire.davdroid.util.PermissionUtils
|
||||
import at.bitfire.davdroid.util.packageChangedFlow
|
||||
import at.bitfire.ical4android.TaskProvider
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.logging.Level
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class PermissionsActivity: AppCompatActivity() {
|
||||
|
||||
val model by viewModels<Model>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContent {
|
||||
M2Theme {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
BasicTopAppBar(
|
||||
titleStringRes = R.string.app_settings_security_app_permissions
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
PermissionsContent(modifier = Modifier.padding(paddingValues), model)
|
||||
}
|
||||
}
|
||||
PermissionsScreen(
|
||||
onNavigateUp = ::onSupportNavigateUp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
model.checkPermissions()
|
||||
}
|
||||
|
||||
|
||||
class Model(app: Application): AndroidViewModel(app) {
|
||||
|
||||
var needKeepPermissions by mutableStateOf(false)
|
||||
var openTasksAvailable by mutableStateOf(false)
|
||||
var tasksOrgAvailable by mutableStateOf(false)
|
||||
var jtxAvailable by mutableStateOf(false)
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
packageChangedFlow(app).collect {
|
||||
checkPermissions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainThread
|
||||
fun checkPermissions() {
|
||||
val pm = getApplication<Application>().packageManager
|
||||
|
||||
// auto-reset permissions
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
needKeepPermissions = pm.isAutoRevokeWhitelisted
|
||||
}
|
||||
|
||||
openTasksAvailable = pm.resolveContentProvider(TaskProvider.ProviderName.OpenTasks.authority, 0) != null
|
||||
tasksOrgAvailable = pm.resolveContentProvider(TaskProvider.ProviderName.TasksOrg.authority, 0) != null
|
||||
jtxAvailable = pm.resolveContentProvider(TaskProvider.ProviderName.JtxBoard.authority, 0) != null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun PermissionsContent(
|
||||
modifier: Modifier = Modifier,
|
||||
model: PermissionsActivity.Model
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
PermissionsCardContent(
|
||||
keepPermissions = model.needKeepPermissions,
|
||||
onKeepPermissionsRequested = {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
val intent = Intent(
|
||||
Intent.ACTION_AUTO_REVOKE_PERMISSIONS,
|
||||
Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)
|
||||
)
|
||||
try {
|
||||
context.startActivity(intent)
|
||||
Toast.makeText(context, R.string.permissions_autoreset_instruction, Toast.LENGTH_LONG).show()
|
||||
} catch (e: Exception) {
|
||||
Logger.log.log(Level.WARNING, "Couldn't start Keep Permissions activity", e)
|
||||
}
|
||||
}
|
||||
},
|
||||
openTasksAvailable = model.openTasksAvailable,
|
||||
tasksOrgAvailable = model.tasksOrgAvailable,
|
||||
jtxAvailable = model.jtxAvailable,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, showSystemUi = true)
|
||||
@Composable
|
||||
fun PermissionsCard_Preview() {
|
||||
M2Theme {
|
||||
PermissionsCardContent(
|
||||
keepPermissions = true,
|
||||
onKeepPermissionsRequested = {},
|
||||
openTasksAvailable = true,
|
||||
tasksOrgAvailable = true,
|
||||
jtxAvailable = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PermissionsCardContent(
|
||||
keepPermissions: Boolean?,
|
||||
onKeepPermissionsRequested: () -> Unit,
|
||||
openTasksAvailable: Boolean?,
|
||||
tasksOrgAvailable: Boolean?,
|
||||
jtxAvailable: Boolean?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
CardWithImage(
|
||||
title = stringResource(R.string.permissions_title),
|
||||
message = stringResource(
|
||||
R.string.permissions_text,
|
||||
stringResource(R.string.app_name)
|
||||
),
|
||||
image = painterResource(R.drawable.intro_permissions),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
if (keepPermissions != null) {
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_autoreset_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_autoreset_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_autoreset_status_off),
|
||||
allPermissionsGranted = keepPermissions,
|
||||
onLaunchRequest = onKeepPermissionsRequested,
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
|
||||
val allPermissions = mutableListOf<String>()
|
||||
allPermissions.addAll(PermissionUtils.CONTACT_PERMISSIONS)
|
||||
allPermissions.addAll(PermissionUtils.CALENDAR_PERMISSIONS)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
allPermissions += Manifest.permission.POST_NOTIFICATIONS
|
||||
if (openTasksAvailable == true)
|
||||
allPermissions.addAll(TaskProvider.PERMISSIONS_OPENTASKS)
|
||||
if (tasksOrgAvailable == true)
|
||||
allPermissions.addAll(TaskProvider.PERMISSIONS_TASKS_ORG)
|
||||
if (jtxAvailable == true)
|
||||
allPermissions.addAll(TaskProvider.PERMISSIONS_JTX)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_all_title),
|
||||
permissions = allPermissions,
|
||||
summaryWhenGranted = stringResource(R.string.permissions_all_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_all_status_off),
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_notification_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_notification_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_notification_status_off),
|
||||
permissions = listOf(Manifest.permission.POST_NOTIFICATIONS),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_calendar_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_calendar_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_calendar_status_off),
|
||||
permissions = PermissionUtils.CALENDAR_PERMISSIONS.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_contacts_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_contacts_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_contacts_status_off),
|
||||
permissions = PermissionUtils.CONTACT_PERMISSIONS.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
if (jtxAvailable == true)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_jtx_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_tasks_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_tasks_status_off),
|
||||
permissions = TaskProvider.PERMISSIONS_JTX.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
if (openTasksAvailable == true)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_opentasks_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_tasks_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_tasks_status_off),
|
||||
permissions = TaskProvider.PERMISSIONS_OPENTASKS.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
if (tasksOrgAvailable == true)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_tasksorg_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_tasks_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_tasks_status_off),
|
||||
permissions = TaskProvider.PERMISSIONS_TASKS_ORG.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.permissions_app_settings_hint),
|
||||
style = MaterialTheme.typography.body1,
|
||||
modifier = Modifier.padding(top = 24.dp)
|
||||
)
|
||||
|
||||
OutlinedButton(
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
onClick = { PermissionUtils.showAppSettings(context) }
|
||||
) {
|
||||
Text(stringResource(R.string.permissions_app_settings).uppercase())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package at.bitfire.davdroid.ui
|
||||
|
||||
import android.app.Application
|
||||
import android.os.Build
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import at.bitfire.davdroid.util.packageChangedFlow
|
||||
import at.bitfire.ical4android.TaskProvider
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class PermissionsModel @Inject constructor(
|
||||
val context: Application
|
||||
): ViewModel() {
|
||||
|
||||
var needKeepPermissions by mutableStateOf(false)
|
||||
private set
|
||||
var openTasksAvailable by mutableStateOf(false)
|
||||
private set
|
||||
var tasksOrgAvailable by mutableStateOf(false)
|
||||
private set
|
||||
var jtxAvailable by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
// check permissions when a package (e.g. tasks app) is (un)installed
|
||||
packageChangedFlow(context).collect {
|
||||
checkPermissions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkPermissions() {
|
||||
val pm = context.packageManager
|
||||
|
||||
// auto-reset permissions
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
needKeepPermissions = pm.isAutoRevokeWhitelisted
|
||||
}
|
||||
|
||||
openTasksAvailable = pm.resolveContentProvider(TaskProvider.ProviderName.OpenTasks.authority, 0) != null
|
||||
tasksOrgAvailable = pm.resolveContentProvider(TaskProvider.ProviderName.TasksOrg.authority, 0) != null
|
||||
jtxAvailable = pm.resolveContentProvider(TaskProvider.ProviderName.JtxBoard.authority, 0) != null
|
||||
}
|
||||
|
||||
}
|
253
app/src/main/kotlin/at/bitfire/davdroid/ui/PermissionsScreen.kt
Normal file
253
app/src/main/kotlin/at/bitfire/davdroid/ui/PermissionsScreen.kt
Normal file
|
@ -0,0 +1,253 @@
|
|||
package at.bitfire.davdroid.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
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.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import at.bitfire.davdroid.BuildConfig
|
||||
import at.bitfire.davdroid.R
|
||||
import at.bitfire.davdroid.log.Logger
|
||||
import at.bitfire.davdroid.ui.composable.CardWithImage
|
||||
import at.bitfire.davdroid.ui.composable.PermissionSwitchRow
|
||||
import at.bitfire.davdroid.util.PermissionUtils
|
||||
import at.bitfire.ical4android.TaskProvider
|
||||
import java.util.logging.Level
|
||||
|
||||
/**
|
||||
* Used when "Manage permissions" is selected in the settings.
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PermissionsScreen(
|
||||
onNavigateUp: () -> Unit
|
||||
) {
|
||||
AppTheme {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text(stringResource(R.string.app_settings_security_app_permissions)) },
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = onNavigateUp
|
||||
) {
|
||||
Icon(Icons.AutoMirrored.Default.ArrowBack, stringResource(R.string.navigate_up))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
PermissionsScreen(modifier = Modifier.padding(paddingValues))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by [PermissionsScreen] and directly embedded in [at.bitfire.davdroid.ui.intro.PermissionsIntroPage].
|
||||
*/
|
||||
@Composable
|
||||
fun PermissionsScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
model: PermissionsModel = viewModel()
|
||||
) {
|
||||
// check permissions when the lifecycle owner (for instance Activity) is resumed
|
||||
val lifecycle = LocalLifecycleOwner.current.lifecycle
|
||||
DisposableEffect(lifecycle) {
|
||||
val observer = object: DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
model.checkPermissions()
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle.addObserver(observer)
|
||||
onDispose {
|
||||
lifecycle.removeObserver(observer)
|
||||
}
|
||||
}
|
||||
|
||||
val context = LocalContext.current
|
||||
PermissionsScreen(
|
||||
keepPermissions = model.needKeepPermissions,
|
||||
onKeepPermissionsRequested = {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
val intent = Intent(
|
||||
Intent.ACTION_AUTO_REVOKE_PERMISSIONS,
|
||||
Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)
|
||||
)
|
||||
try {
|
||||
context.startActivity(intent)
|
||||
Toast.makeText(context, R.string.permissions_autoreset_instruction, Toast.LENGTH_LONG).show()
|
||||
} catch (e: Exception) {
|
||||
Logger.log.log(Level.WARNING, "Couldn't start Keep Permissions activity", e)
|
||||
}
|
||||
}
|
||||
},
|
||||
openTasksAvailable = model.openTasksAvailable,
|
||||
tasksOrgAvailable = model.tasksOrgAvailable,
|
||||
jtxAvailable = model.jtxAvailable,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun PermissionsScreen(
|
||||
keepPermissions: Boolean?,
|
||||
onKeepPermissionsRequested: () -> Unit,
|
||||
openTasksAvailable: Boolean?,
|
||||
tasksOrgAvailable: Boolean?,
|
||||
jtxAvailable: Boolean?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
CardWithImage(
|
||||
title = stringResource(R.string.permissions_title),
|
||||
message = stringResource(
|
||||
R.string.permissions_text,
|
||||
stringResource(R.string.app_name)
|
||||
),
|
||||
image = painterResource(R.drawable.intro_permissions),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
if (keepPermissions != null) {
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_autoreset_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_autoreset_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_autoreset_status_off),
|
||||
allPermissionsGranted = keepPermissions,
|
||||
onLaunchRequest = onKeepPermissionsRequested,
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
|
||||
val allPermissions = mutableListOf<String>()
|
||||
allPermissions.addAll(PermissionUtils.CONTACT_PERMISSIONS)
|
||||
allPermissions.addAll(PermissionUtils.CALENDAR_PERMISSIONS)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
allPermissions += Manifest.permission.POST_NOTIFICATIONS
|
||||
if (openTasksAvailable == true)
|
||||
allPermissions.addAll(TaskProvider.PERMISSIONS_OPENTASKS)
|
||||
if (tasksOrgAvailable == true)
|
||||
allPermissions.addAll(TaskProvider.PERMISSIONS_TASKS_ORG)
|
||||
if (jtxAvailable == true)
|
||||
allPermissions.addAll(TaskProvider.PERMISSIONS_JTX)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_all_title),
|
||||
permissions = allPermissions,
|
||||
summaryWhenGranted = stringResource(R.string.permissions_all_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_all_status_off),
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_notification_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_notification_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_notification_status_off),
|
||||
permissions = listOf(Manifest.permission.POST_NOTIFICATIONS),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_calendar_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_calendar_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_calendar_status_off),
|
||||
permissions = PermissionUtils.CALENDAR_PERMISSIONS.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_contacts_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_contacts_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_contacts_status_off),
|
||||
permissions = PermissionUtils.CONTACT_PERMISSIONS.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
if (jtxAvailable == true)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_jtx_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_tasks_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_tasks_status_off),
|
||||
permissions = TaskProvider.PERMISSIONS_JTX.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
if (openTasksAvailable == true)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_opentasks_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_tasks_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_tasks_status_off),
|
||||
permissions = TaskProvider.PERMISSIONS_OPENTASKS.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
if (tasksOrgAvailable == true)
|
||||
PermissionSwitchRow(
|
||||
text = stringResource(R.string.permissions_tasksorg_title),
|
||||
summaryWhenGranted = stringResource(R.string.permissions_tasks_status_on),
|
||||
summaryWhenNotGranted = stringResource(R.string.permissions_tasks_status_off),
|
||||
permissions = TaskProvider.PERMISSIONS_TASKS_ORG.toList(),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.permissions_app_settings_hint),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier.padding(top = 24.dp)
|
||||
)
|
||||
|
||||
val context = LocalContext.current
|
||||
OutlinedButton(
|
||||
modifier = Modifier.padding(vertical = 8.dp),
|
||||
onClick = { PermissionUtils.showAppSettings(context) }
|
||||
) {
|
||||
Text(stringResource(R.string.permissions_app_settings))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PermissionsCard_Preview() {
|
||||
AppTheme {
|
||||
PermissionsScreen(
|
||||
keepPermissions = true,
|
||||
onKeepPermissionsRequested = {},
|
||||
openTasksAvailable = true,
|
||||
tasksOrgAvailable = true,
|
||||
jtxAvailable = true
|
||||
)
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import at.bitfire.davdroid.R
|
||||
|
||||
@Composable
|
||||
@Deprecated("Directly use TopAppBar instead.", replaceWith = ReplaceWith("TopAppBar"))
|
||||
fun BasicTopAppBar(
|
||||
@StringRes titleStringRes: Int,
|
||||
onNavigateUp: () -> Unit
|
||||
|
|
|
@ -12,12 +12,12 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.TabletAndroid
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
@ -85,13 +85,13 @@ fun CardWithImage(
|
|||
Text(
|
||||
text = title,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = MaterialTheme.typography.h6
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
subtitle?.let {
|
||||
Text(
|
||||
text = it,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = MaterialTheme.typography.subtitle1
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ fun CardWithImage(
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp),
|
||||
style = MaterialTheme.typography.body1
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ package at.bitfire.davdroid.ui.composable
|
|||
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.material3.MaterialTheme
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
@ -40,12 +40,12 @@ fun PermissionSwitchRow(
|
|||
text = text,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
fontWeight = fontWeight,
|
||||
style = MaterialTheme.typography.body1
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Text(
|
||||
text = if (allPermissionsGranted) summaryWhenGranted else summaryWhenNotGranted,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = MaterialTheme.typography.body2
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
}
|
||||
Switch(
|
||||
|
|
|
@ -7,15 +7,16 @@ package at.bitfire.davdroid.ui.intro
|
|||
import android.app.Application
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import at.bitfire.davdroid.ui.PermissionsActivity
|
||||
import at.bitfire.davdroid.ui.PermissionsContent
|
||||
import at.bitfire.davdroid.ui.PermissionsScreen
|
||||
import at.bitfire.davdroid.ui.PermissionsModel
|
||||
import at.bitfire.davdroid.util.PermissionUtils
|
||||
import at.bitfire.davdroid.util.PermissionUtils.CALENDAR_PERMISSIONS
|
||||
import at.bitfire.davdroid.util.PermissionUtils.CONTACT_PERMISSIONS
|
||||
import at.bitfire.ical4android.TaskProvider
|
||||
|
||||
class PermissionsIntroPage: IntroPage {
|
||||
|
||||
var model: PermissionsActivity.Model? = null
|
||||
var model: PermissionsModel? = null
|
||||
|
||||
override fun getShowPolicy(application: Application): IntroPage.ShowPolicy {
|
||||
// show PermissionsFragment as intro fragment when no permissions are granted
|
||||
|
@ -31,10 +32,10 @@ class PermissionsIntroPage: IntroPage {
|
|||
|
||||
@Composable
|
||||
override fun ComposePage() {
|
||||
val newModel: PermissionsActivity.Model = viewModel()
|
||||
val newModel: PermissionsModel = viewModel()
|
||||
model = newModel
|
||||
|
||||
PermissionsContent(model = newModel)
|
||||
PermissionsScreen(model = newModel)
|
||||
}
|
||||
|
||||
// Check whether permissions have changed after user comes back from settings app
|
||||
|
|
Loading…
Reference in a new issue