Compare commits

..
2 Commits
Author SHA1 Message Date
omni 2a538fdf1c feat: added sync with WearOS on card delete 2026-06-24 20:14:10 +03:00
omni ff214eb3d2 refactor: updated sync with WearOS logic 2026-06-24 20:11:19 +03:00
6 changed files with 55 additions and 18 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ android {
minSdk = 30 minSdk = 30
targetSdk = 36 targetSdk = 36
versionCode = generateVersionCode() versionCode = generateVersionCode()
versionName = "4.2.1" versionName = "4.3.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -63,6 +63,7 @@ class MainActivity : ComponentActivity() {
MainPage(innerPadding, cards, onDeleteCard = { cardId -> MainPage(innerPadding, cards, onDeleteCard = { cardId ->
db.removeCard(cardId) db.removeCard(cardId)
cards.removeIf { it.id == cardId } cards.removeIf { it.id == cardId }
syncCardsWithWatch(this, db.getCards())
}, getDbFun = { }, getDbFun = {
return@MainPage db return@MainPage db
}) })
@@ -76,6 +77,8 @@ class MainActivity : ComponentActivity() {
cards.clear() cards.clear()
cards.addAll(db.getCards()) cards.addAll(db.getCards())
syncCardsWithWatch(this, db.getCards())
} }
} }
@@ -114,12 +117,13 @@ fun MainPage(
NavigationPageData(stringResource(R.string.do_add_card), Icons.Outlined.Add, EditCardActivity::class.java), NavigationPageData(stringResource(R.string.do_add_card), Icons.Outlined.Add, EditCardActivity::class.java),
NavigationPageData(stringResource(R.string.do_sync), Icons.Outlined.Sync) { NavigationPageData(stringResource(R.string.do_sync), Icons.Outlined.Sync) {
Toast.makeText(context, context.getString(R.string.sync_in_progress), Toast.LENGTH_SHORT).show() Toast.makeText(context, context.getString(R.string.sync_in_progress), Toast.LENGTH_SHORT).show()
sendToWatch(context, "/updateCards", Json.encodeToString(getDbFun().getCards())) { isSuccess ->
if (isSuccess) { val isSuccess = syncCardsWithWatch(context, getDbFun().getCards())
Toast.makeText(context, context.getString(R.string.sync_is_successful), Toast.LENGTH_SHORT).show()
} else { if (isSuccess) {
Toast.makeText(context, context.getString(R.string.sync_is_fail), Toast.LENGTH_LONG).show() Toast.makeText(context, context.getString(R.string.sync_is_successful), Toast.LENGTH_SHORT).show()
} } else {
Toast.makeText(context, context.getString(R.string.sync_is_fail), Toast.LENGTH_LONG).show()
} }
}, },
NavigationPageData(stringResource(R.string.open_backup_menu), Icons.Outlined.Backup, BackupActivity::class.java), NavigationPageData(stringResource(R.string.open_backup_menu), Icons.Outlined.Backup, BackupActivity::class.java),
@@ -14,7 +14,9 @@ import com.journeyapps.barcodescanner.BarcodeEncoder
import org.json.JSONObject import org.json.JSONObject
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import android.util.Base64 import android.util.Base64
import android.widget.Toast
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import kotlinx.serialization.json.Json
fun generateCode(value: String, format: BarcodeFormat): Bitmap { fun generateCode(value: String, format: BarcodeFormat): Bitmap {
val writer = MultiFormatWriter() val writer = MultiFormatWriter()
@@ -33,12 +35,14 @@ fun generateCode(value: String, format: BarcodeFormat): Bitmap {
return BarcodeEncoder().createBitmap(matrix) return BarcodeEncoder().createBitmap(matrix)
} }
fun sendToWatch(context: Context, path: String, message: String, onResult: (Boolean) -> Unit) { fun sendToWatch(context: Context, path: String, message: String): Boolean {
val nodeClient = Wearable.getNodeClient(context) val nodeClient = Wearable.getNodeClient(context)
var isSuccess = false
nodeClient.connectedNodes.addOnSuccessListener { nodes -> nodeClient.connectedNodes.addOnSuccessListener { nodes ->
if (nodes.isEmpty()) { if (nodes.isEmpty()) {
onResult(false) isSuccess = false
return@addOnSuccessListener return@addOnSuccessListener
} }
@@ -59,13 +63,19 @@ fun sendToWatch(context: Context, path: String, message: String, onResult: (Bool
} }
if (completedCount == nodes.size) { if (completedCount == nodes.size) {
onResult(isAnySuccess) isSuccess = isAnySuccess
} }
}.addOnFailureListener(context.mainExecutor) { }.addOnFailureListener(context.mainExecutor) {
onResult(false) isSuccess = false
} }
} }
} }
return isSuccess
}
fun syncCardsWithWatch(context: Context, cards: List<CardInfo>): Boolean {
return sendToWatch(context, "/updateCards", Json.encodeToString(cards))
} }
fun checkCardData(name: String, value: String): Int? { fun checkCardData(name: String, value: String): Int? {
+2 -1
View File
@@ -23,7 +23,7 @@ android {
minSdk = 30 minSdk = 30
targetSdk = 36 targetSdk = 36
versionCode = generateVersionCode() versionCode = generateVersionCode()
versionName = "3.2.0" versionName = "3.3.0"
} }
buildTypes { buildTypes {
@@ -72,4 +72,5 @@ dependencies {
implementation(libs.material) implementation(libs.material)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
implementation("androidx.compose.material:material-icons-extended") implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.lifecycle:lifecycle-process:2.8.7")
} }
@@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@@ -22,16 +23,25 @@ import ru.omni_devel.cards.R
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
private lateinit var db: DbHelper private lateinit var db: DbHelper
private val cardsState = mutableStateOf<List<CardInfo>>(emptyList())
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
db = DbHelper(this, null) db = DbHelper(this, null)
cardsState.value = db.getCards()
setContent { setContent {
App(db.getCards()) App(cardsState.value)
} }
} }
override fun onResume() {
super.onResume()
cardsState.value = db.getCards()
}
} }
@SuppressLint("UnusedBoxWithConstraintsScope") @SuppressLint("UnusedBoxWithConstraintsScope")
@@ -8,6 +8,8 @@ import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.WearableListenerService import com.google.android.gms.wearable.WearableListenerService
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import ru.omni_devel.cards.R import ru.omni_devel.cards.R
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.Lifecycle
class MessagesReceiver : WearableListenerService() { class MessagesReceiver : WearableListenerService() {
private lateinit var db: DbHelper private lateinit var db: DbHelper
@@ -28,13 +30,23 @@ class MessagesReceiver : WearableListenerService() {
db.clearDatabase() db.clearDatabase()
db.addCards(cards) db.addCards(cards)
Handler(Looper.getMainLooper()).post { val isAppInForeground = ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(
Toast.makeText(this, this.getString(R.string.sync_is_successful), Toast.LENGTH_SHORT).show() Lifecycle.State.STARTED
)
val intent = Intent(this, MainActivity::class.java).apply { if (isAppInForeground) {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP Handler(Looper.getMainLooper()).post {
Toast.makeText(
this,
this.getString(R.string.sync_is_successful),
Toast.LENGTH_SHORT
).show()
val intent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
startActivity(intent)
} }
startActivity(intent)
} }
} }
} }