From 07315fe11b73957d65e5ad1a45881ae6b0bb0478 Mon Sep 17 00:00:00 2001 From: b13st Date: Wed, 24 Jun 2026 15:29:58 +0200 Subject: [PATCH 1/2] Delete character from app after successful HCE transfer to VitalWear watch When sending a character to the VitalWear watch via HCE, the transfer is atomic (single NFC interaction). The character was being left in the app after transfer, allowing it to be cloned indefinitely. Delete the character from the database immediately after sendCharacterToWatch succeeds, matching the behavior of physical bracelet transfers which delete the character once both write phases complete. --- .../vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt index de4d476..32ca62e 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt @@ -231,7 +231,9 @@ class ScanScreenControllerImpl( val proto = VitalWearCharacterExporter(componentActivity, database).buildCharacterProto(characterId) val client = VitalWearHceReaderClient(isoDep) client.sendCharacterToWatch(proto) - Log.i("NFC_WRITE", "Character sent to VitalWear via HCE") + database.userCharacterDao().deleteCharacterById(characterId) + pendingExportCharacterId = null + Log.i("NFC_WRITE", "Character sent to VitalWear and deleted from app (id=$characterId)") componentActivity.runOnUiThread { Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_sent_character_success), Toast.LENGTH_SHORT).show() } From 05f04fdc4958c8722b56754f0fcc33b9825a21d7 Mon Sep 17 00:00:00 2001 From: b13st Date: Wed, 24 Jun 2026 15:40:19 +0200 Subject: [PATCH 2/2] Fix LaunchedEffect key so characterToNfc runs when active character loads When launching the scan screen from the home button, characterId is loaded asynchronously from the active character. The previous key (storageRepository) never re-triggered the effect, so characterToNfc (which sets pendingExportCharacterId) was skipped if characterId was null on first composition, making the HCE delete unreachable. --- .../nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt index 72fc520..47cc4cb 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt @@ -44,14 +44,8 @@ fun ScanScreen( val context = LocalContext.current - LaunchedEffect(storageRepository) { + LaunchedEffect(characterId) { withContext(Dispatchers.IO) { - /* - First check if there is a character sent through the navigation system - If there is not, that means we got here through the home screen nfc button - If we got here through the home screen, it does not hurt to check if there is - an active character. - */ if (characterId != null && nfcCharacter == null) { nfcCharacter = scanScreenController.characterToNfc(characterId) }