package ru.omni_devel.cards import android.net.Uri import android.os.Bundle import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.LocalActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Save import androidx.compose.material.icons.outlined.Restore import androidx.compose.material3.AlertDialog import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import kotlinx.serialization.json.Json import ru.omni_devel.cards.ui.theme.OmniCardsTheme import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource class BackupActivity : ComponentActivity() { private lateinit var db: DbHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() db = DbHelper(this, null) setContent { OmniCardsTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> BackupPage(innerPadding = innerPadding, getDbFun = { return@BackupPage db }) } } } } } @Composable fun BackupPage(innerPadding: PaddingValues, getDbFun: () -> DbHelper) { val context = LocalContext.current val activityContext = LocalActivity.current val showImportDialog = rememberSaveable { mutableStateOf(false) } var pendingUri by rememberSaveable { mutableStateOf(null) } val createBackupLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.CreateDocument("application/json") ) { uri -> uri?.let { try { val jsonData = Json.encodeToString(getDbFun().getCards()) context.contentResolver.openOutputStream(it)?.use { outputStream -> outputStream.write(jsonData.toByteArray()) Toast.makeText(context, context.getString(R.string.backup_successfully_saved), Toast.LENGTH_SHORT).show() activityContext!!.finish() } } catch (e: Exception) { Toast.makeText(context, context.getString(R.string.failed_to_save_backup, e), Toast.LENGTH_LONG).show() } } } val restoreFromBackupLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.GetContent() ) { uri -> uri?.let { pendingUri = it showImportDialog.value = true } } if (showImportDialog.value) { AlertDialog( title = { Text(stringResource(R.string.ask_do_restore)) }, text = { Text(stringResource(R.string.restore_caution)) }, confirmButton = { TextButton( onClick = { showImportDialog.value = false pendingUri?.let { uri -> try { context.contentResolver.openInputStream(uri)?.use { stream -> val json = stream.bufferedReader().use { it.readText() } val cards = Json.decodeFromString>(json) val db = getDbFun() db.clearDatabase() db.addCards(cards) Toast.makeText(context, context.getString(R.string.backup_successfully_restored), Toast.LENGTH_SHORT).show() activityContext!!.finish() } } catch (e: Exception) { Toast.makeText(context, context.getString(R.string.failed_to_restore_backup, e), Toast.LENGTH_LONG).show() } } } ) { Text(stringResource(R.string.yes)) } }, dismissButton = { TextButton( onClick = { showImportDialog.value = false } ) { Text(stringResource(R.string.no)) } }, onDismissRequest = { showImportDialog.value = false }, ) } Page(stringResource(R.string.backup), innerPadding) { AdaptiveButton( modifier = Modifier.fillMaxWidth(), icon = Icons.Outlined.Save, onClick = { createBackupLauncher.launch("omnicards-backup.json") } ) { Text(stringResource(R.string.do_backup)) } AdaptiveButton( modifier = Modifier.fillMaxWidth(), icon = Icons.Outlined.Restore, onClick = { restoreFromBackupLauncher.launch("application/json") } ) { Text(stringResource(R.string.do_restore)) } } }