Compare commits

..

3 Commits

Author SHA1 Message Date
Ricki Hirner
439639d204 Add to "Reset hints" 2026-01-21 15:13:17 +01:00
Ricki Hirner
49cce6aa8f Add BackupsPage UI
- Implement BackupsPage composable with UI elements
- Add strings for backups reminder and acceptance
2026-01-21 14:56:50 +01:00
Ricki Hirner
a1997409b7 Add BackupsPage to intro UI 2026-01-21 14:25:38 +01:00
4 changed files with 143 additions and 0 deletions

View File

@@ -20,6 +20,7 @@ import at.bitfire.davdroid.repository.PreferenceRepository
import at.bitfire.davdroid.settings.Settings
import at.bitfire.davdroid.settings.SettingsManager
import at.bitfire.davdroid.sync.TasksAppManager
import at.bitfire.davdroid.ui.intro.BackupsPage
import at.bitfire.davdroid.ui.intro.BatteryOptimizationsPageModel
import at.bitfire.davdroid.ui.intro.OpenSourcePage
import at.bitfire.davdroid.util.PermissionUtils
@@ -102,6 +103,7 @@ class AppSettingsModel @Inject constructor(
settings.remove(BatteryOptimizationsPageModel.HINT_BATTERY_OPTIMIZATIONS)
settings.remove(BatteryOptimizationsPageModel.HINT_AUTOSTART_PERMISSION)
settings.remove(TasksModel.HINT_OPENTASKS_NOT_INSTALLED)
settings.remove(BackupsPage.Model.SETTING_BACKUPS_ACCEPTED)
settings.remove(OpenSourcePage.Model.SETTING_NEXT_DONATION_POPUP)
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.intro
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
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.outlined.Backup
import androidx.compose.material3.Checkbox
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import at.bitfire.davdroid.R
import at.bitfire.davdroid.settings.SettingsManager
import at.bitfire.davdroid.ui.AppTheme
import at.bitfire.davdroid.ui.composable.CardWithImage
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
class BackupsPage @Inject constructor(
val settingsManager: SettingsManager
): IntroPage() {
override fun getShowPolicy(): ShowPolicy =
if (Model.backupsAccepted(settingsManager))
ShowPolicy.DONT_SHOW
else
ShowPolicy.SHOW_ALWAYS
@Composable
override fun ComposePage() {
val model = hiltViewModel<Model>()
val accepted by model.backupsAcceptedFlow.collectAsStateWithLifecycle(false)
BackupsPage(
accepted = accepted,
updateAccepted = model::setBackupsAccepted
)
}
@HiltViewModel
class Model @Inject constructor(
private val settings: SettingsManager
): ViewModel() {
val backupsAcceptedFlow = settings.getBooleanFlow(SETTING_BACKUPS_ACCEPTED, false)
fun setBackupsAccepted(accepted: Boolean) {
settings.putBoolean(SETTING_BACKUPS_ACCEPTED, accepted)
}
companion object {
/** boolean setting (default: false) */
const val SETTING_BACKUPS_ACCEPTED = "intro_backups_accepted"
fun backupsAccepted(settingsManager: SettingsManager): Boolean =
settingsManager.getBooleanOrNull(SETTING_BACKUPS_ACCEPTED) ?: false
}
}
}
@Composable
fun BackupsPage(
accepted: Boolean,
updateAccepted: (Boolean) -> Unit
) {
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(8.dp)
) {
CardWithImage(
title = stringResource(R.string.intro_backups_title),
icon = Icons.Outlined.Backup,
modifier = Modifier.padding(vertical = 8.dp)
) {
Text(
text = stringResource(R.string.intro_backups_important),
modifier = Modifier.padding(bottom = 8.dp)
)
Text(
text = stringResource(R.string.intro_backups_no_versioning, stringResource(R.string.app_name)),
)
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(top = 8.dp, bottom = 16.dp)
) {
Checkbox(
checked = accepted,
onCheckedChange = updateAccepted
)
Text(
text = stringResource(R.string.intro_backups_accept),
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier
.clickable { updateAccepted(!accepted) }
.padding(start = 8.dp)
)
}
}
}
}
@Preview
@Composable
fun BackupsPagePreview() {
AppTheme {
BackupsPage(
accepted = true,
updateAccepted = {}
)
}
}

View File

@@ -58,6 +58,10 @@
<string name="intro_tasks_tasks_org_info"><![CDATA[Some features <a href="https://www.davx5.com/faq/tasks/advanced-task-features">are not supported</a>.]]></string>
<string name="intro_tasks_no_app_store">No app store available</string>
<string name="intro_tasks_dont_show">I don\'t need tasks support.*</string>
<string name="intro_backups_title">Backups reminder</string>
<string name="intro_backups_important">It\'s important to back up your data (including contacts and calendars) regularly to prevent potential data loss.</string>
<string name="intro_backups_no_versioning">%s synchronizes changes and deletions but does NOT function as a backup tool or provide version history.</string>
<string name="intro_backups_accept">I already have a backup solution in place or I don\'t need one.</string>
<string name="intro_open_source_title">Open-source software</string>
<string name="intro_open_source_text">We\'re happy that you use %s, which is open-source software. Development, maintenance and support are hard work. Please consider contributing (there are many ways) or a donation. It would be highly appreciated!</string>
<string name="intro_open_source_details">How to contribute/donate</string>

View File

@@ -7,6 +7,7 @@ package at.bitfire.davdroid.ui.intro
import javax.inject.Inject
class OseIntroPageFactory @Inject constructor(
backupsPage: BackupsPage,
batteryOptimizationsPage: BatteryOptimizationsPage,
openSourcePage: OpenSourcePage,
permissionsIntroPage: PermissionsIntroPage,
@@ -18,6 +19,7 @@ class OseIntroPageFactory @Inject constructor(
tasksIntroPage,
permissionsIntroPage,
batteryOptimizationsPage,
backupsPage,
openSourcePage
)