package ru.omni_devel.cards import android.net.Uri import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Download import androidx.compose.material.icons.filled.Restore import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import kotlinx.serialization.json.Json @Composable fun BackupScreen( db: DbHelper, onBack: () -> Unit, ) { val context = LocalContext.current var showRestoreDialog by remember { mutableStateOf(false) } var pendingUri by remember { mutableStateOf(null) } val createBackupLauncher = rememberLauncherForActivityResult( ActivityResultContracts.CreateDocument("application/json") ) { uri -> uri?.let { try { val json = Json.encodeToString(db.getCards()) context.contentResolver.openOutputStream(it)?.use { stream -> stream.write(json.toByteArray()) } Toast.makeText(context, context.getString(R.string.backup_successfully_saved), Toast.LENGTH_SHORT).show() } catch (e: Exception) { Toast.makeText(context, context.getString(R.string.failed_to_save_backup, e), Toast.LENGTH_LONG).show() } } } val restoreLauncher = rememberLauncherForActivityResult( ActivityResultContracts.GetContent() ) { uri -> uri?.let { pendingUri = it showRestoreDialog = true } } if (showRestoreDialog) { AlertDialog( onDismissRequest = { showRestoreDialog = false }, title = { Text(stringResource(R.string.ask_do_restore)) }, text = { Text(stringResource(R.string.restore_caution)) }, confirmButton = { TextButton(onClick = { showRestoreDialog = false pendingUri?.let { uri -> try { context.contentResolver.openInputStream(uri)?.use { stream -> val json = stream.bufferedReader().use { it.readText() } val cards = Json.decodeFromString>(json) db.clearDatabase() db.addCards(cards) } Toast.makeText(context, context.getString(R.string.backup_successfully_restored), Toast.LENGTH_SHORT).show() onBack() } 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 = { showRestoreDialog = false }) { Text(stringResource(R.string.no)) } } ) } Column( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.surfaceContainer) .statusBarsPadding() ) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 6.dp, vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { IconButton(onClick = onBack) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } Text(stringResource(R.string.backup), style = MaterialTheme.typography.titleLarge) } Column( modifier = Modifier.padding(horizontal = 20.dp, vertical = 12.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { Button( onClick = { createBackupLauncher.launch("omnicards-backup.json") }, modifier = Modifier .fillMaxWidth() .height(56.dp) ) { Icon(Icons.Filled.Download, contentDescription = null) Spacer(Modifier.width(8.dp)) Text(stringResource(R.string.do_backup)) } OutlinedButton( onClick = { restoreLauncher.launch("application/json") }, modifier = Modifier .fillMaxWidth() .height(56.dp) ) { Icon(Icons.Filled.Restore, contentDescription = null) Spacer(Modifier.width(8.dp)) Text(stringResource(R.string.do_restore)) } } } }