feat: full md3 redesign and few tweaks

fully redesigned android and wearos app

auto sync with wearos

enabled minify
This commit is contained in:
Fimkov
2026-06-19 12:06:49 +07:00
parent 1c76705551
commit e62b7f4741
43 changed files with 4013 additions and 1199 deletions
@@ -0,0 +1,155 @@
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<Uri?>(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<List<CardInfo>>(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))
}
}
}
}