Skip to content
14 changes: 12 additions & 2 deletions android/app/src/main/java/org/bitcoinppl/cove/ScanManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,18 @@ class ScanManager private constructor() {
}

try {
LabelManager(id = selectedWallet).use { it.importLabels(multiFormat.v1) }
app.alertState = TaggedItem(AppAlertState.ImportedLabelsSuccessfully)
val result = LabelManager(id = selectedWallet).use { it.importLabels(multiFormat.v1) }
if (result.skipped > 0u) {
val noun = if (result.skipped == 1u) "label" else "labels"
app.alertState = TaggedItem(
AppAlertState.General(
title = "Labels Imported",
message = "Could not import ${result.skipped} $noun"
)
Comment thread
Sandipmandal25 marked this conversation as resolved.
)
} else {
app.alertState = TaggedItem(AppAlertState.ImportedLabelsSuccessfully)
}

app.walletManager?.let { wm ->
mainScope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ fun NfcLabelImportSheet(
labelManager: LabelManager,
onDismiss: () -> Unit,
onSuccess: () -> Unit,
onPartialSuccess: (skipped: UInt) -> Unit,
onError: (String) -> Unit,
) {
val context = LocalContext.current
Expand Down Expand Up @@ -86,11 +87,13 @@ fun NfcLabelImportSheet(
// try to parse the NFC data as BIP329 labels
try {
result.text?.let { text ->
// try to import the labels
labelManager.import(text.trim())
// success! dismiss and notify
val importResult = labelManager.import(text.trim())
nfcReader.reset()
onSuccess()
if (importResult.skipped > 0u) {
onPartialSuccess(importResult.skipped)
} else {
onSuccess()
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return@collect
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,37 @@ fun rememberWalletExportLaunchers(
}
} ?: throw Exception("Unable to read file")

// validate import was successful before showing success message
currentManager.rust.labelManager().use { labelManager ->
val result = currentManager.rust.labelManager().use { labelManager ->
labelManager.import(fileContents.trim())
}

// refresh transactions with updated labels
try {
val refreshFailed = try {
currentManager.rust.getTransactions()
false
} catch (refreshError: Exception) {
android.util.Log.e(tag, "failed to refresh transactions after label import", refreshError)
snackbarHostState.showSnackbar("Labels imported successfully, but transaction list may need manual refresh")
return@launch
true
}

val skippedMsg = if (result.skipped > 0u) {
val noun = if (result.skipped == 1u) "label" else "labels"
"Could not import ${result.skipped} $noun"
} else {
null
}

snackbarHostState.showSnackbar("Labels imported successfully")
val msg = when {
skippedMsg != null && refreshFailed ->
"Labels imported. $skippedMsg. Transaction list may need manual refresh"
skippedMsg != null ->
"Labels imported. $skippedMsg"
refreshFailed ->
"Labels imported successfully, but transaction list may need manual refresh"
else ->
"Labels imported successfully"
}
snackbarHostState.showSnackbar(msg)
} catch (e: Exception) {
android.util.Log.e(tag, "error importing labels", e)
snackbarHostState.showSnackbar("Unable to import labels: ${e.localizedMessage ?: e.message}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,20 @@ internal fun WalletSheetsHost(
}
}
},
onPartialSuccess = { skipped ->
onDismissNfcScanner()
scope.launch {
val noun = if (skipped == 1u) "label" else "labels"
val skippedMsg = "Labels imported. Could not import $skipped $noun"
try {
manager.rust.getTransactions()
snackbarHostState.showSnackbar(skippedMsg)
} catch (e: Exception) {
android.util.Log.e(tag, "Failed to refresh transactions after partial NFC label import", e)
snackbarHostState.showSnackbar("$skippedMsg. Transaction list may need manual refresh")
}
Comment thread
Sandipmandal25 marked this conversation as resolved.
}
},
onError = { errorMsg ->
onDismissNfcScanner()
scope.launch {
Expand Down
69 changes: 57 additions & 12 deletions android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2388,9 +2388,9 @@ internal object UniffiLib {
external fun uniffi_cove_fn_method_labelmanager_has_labels(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus,
): Byte
external fun uniffi_cove_fn_method_labelmanager_import(`ptr`: Long,`jsonl`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): Unit
): RustBuffer.ByValue
external fun uniffi_cove_fn_method_labelmanager_importlabels(`ptr`: Long,`labels`: Long,uniffi_out_err: UniffiRustCallStatus,
): Unit
): RustBuffer.ByValue
external fun uniffi_cove_fn_method_labelmanager_insert_or_update_labels_for_txn(`ptr`: Long,`details`: Long,`label`: RustBuffer.ByValue,`origin`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): Unit
external fun uniffi_cove_fn_method_labelmanager_transaction_label(`ptr`: Long,`txId`: Long,uniffi_out_err: UniffiRustCallStatus,
Expand Down Expand Up @@ -4004,10 +4004,10 @@ private fun uniffiCheckApiChecksums(lib: IntegrityCheckingUniffiLib) {
if (lib.uniffi_cove_checksum_method_labelmanager_has_labels() != 29517.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_cove_checksum_method_labelmanager_import() != 37462.toShort()) {
if (lib.uniffi_cove_checksum_method_labelmanager_import() != 57006.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_cove_checksum_method_labelmanager_importlabels() != 52503.toShort()) {
if (lib.uniffi_cove_checksum_method_labelmanager_importlabels() != 8041.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_cove_checksum_method_labelmanager_insert_or_update_labels_for_txn() != 51703.toShort()) {
Expand Down Expand Up @@ -14001,9 +14001,9 @@ public interface LabelManagerInterface {

fun `hasLabels`(): kotlin.Boolean

fun `import`(`jsonl`: kotlin.String)
fun `import`(`jsonl`: kotlin.String): LabelParseReport

fun `importLabels`(`labels`: Bip329Labels)
fun `importLabels`(`labels`: Bip329Labels): LabelParseReport

fun `insertOrUpdateLabelsForTxn`(`details`: TransactionDetails, `label`: kotlin.String, `origin`: kotlin.String?)

Expand Down Expand Up @@ -14210,8 +14210,8 @@ open class LabelManager: Disposable, AutoCloseable, LabelManagerInterface



@Throws(LabelManagerException::class)override fun `import`(`jsonl`: kotlin.String)
=
@Throws(LabelManagerException::class)override fun `import`(`jsonl`: kotlin.String): LabelParseReport {
return FfiConverterTypeLabelParseReport.lift(
callWithHandle {
uniffiRustCallWithError(LabelManagerException) { _status ->
UniffiLib.uniffi_cove_fn_method_labelmanager_import(
Expand All @@ -14220,12 +14220,13 @@ open class LabelManager: Disposable, AutoCloseable, LabelManagerInterface
FfiConverterString.lower(`jsonl`),_status)
}
}

)
}



@Throws(LabelManagerException::class)override fun `importLabels`(`labels`: Bip329Labels)
=
@Throws(LabelManagerException::class)override fun `importLabels`(`labels`: Bip329Labels): LabelParseReport {
return FfiConverterTypeLabelParseReport.lift(
callWithHandle {
uniffiRustCallWithError(LabelManagerException) { _status ->
UniffiLib.uniffi_cove_fn_method_labelmanager_importlabels(
Expand All @@ -14234,7 +14235,8 @@ open class LabelManager: Disposable, AutoCloseable, LabelManagerInterface
FfiConverterTypeBip329Labels.lower(`labels`),_status)
}
}

)
}



Expand Down Expand Up @@ -27736,6 +27738,8 @@ data class BackupImportReport (
,
var `walletsWithLabelsImported`: kotlin.UInt
,
var `labelsSkipped`: kotlin.UInt
,
var `labelsFailedWalletNames`: List<kotlin.String>
,
var `labelsFailedErrors`: List<kotlin.String>
Expand Down Expand Up @@ -27777,6 +27781,7 @@ public object FfiConverterTypeBackupImportReport: FfiConverterRustBuffer<BackupI
FfiConverterSequenceString.read(buf),
FfiConverterSequenceString.read(buf),
FfiConverterUInt.read(buf),
FfiConverterUInt.read(buf),
FfiConverterSequenceString.read(buf),
FfiConverterSequenceString.read(buf),
FfiConverterBoolean.read(buf),
Expand All @@ -27795,6 +27800,7 @@ public object FfiConverterTypeBackupImportReport: FfiConverterRustBuffer<BackupI
FfiConverterSequenceString.allocationSize(value.`failedWalletNames`) +
FfiConverterSequenceString.allocationSize(value.`failedWalletErrors`) +
FfiConverterUInt.allocationSize(value.`walletsWithLabelsImported`) +
FfiConverterUInt.allocationSize(value.`labelsSkipped`) +
FfiConverterSequenceString.allocationSize(value.`labelsFailedWalletNames`) +
FfiConverterSequenceString.allocationSize(value.`labelsFailedErrors`) +
FfiConverterBoolean.allocationSize(value.`settingsRestored`) +
Expand All @@ -27812,6 +27818,7 @@ public object FfiConverterTypeBackupImportReport: FfiConverterRustBuffer<BackupI
FfiConverterSequenceString.write(value.`failedWalletNames`, buf)
FfiConverterSequenceString.write(value.`failedWalletErrors`, buf)
FfiConverterUInt.write(value.`walletsWithLabelsImported`, buf)
FfiConverterUInt.write(value.`labelsSkipped`, buf)
FfiConverterSequenceString.write(value.`labelsFailedWalletNames`, buf)
FfiConverterSequenceString.write(value.`labelsFailedErrors`, buf)
FfiConverterBoolean.write(value.`settingsRestored`, buf)
Expand Down Expand Up @@ -29435,6 +29442,44 @@ public object FfiConverterTypeLabelExportResult: FfiConverterRustBuffer<LabelExp



data class LabelParseReport (
var `imported`: kotlin.UInt
,
var `skipped`: kotlin.UInt

){





companion object
}

/**
* @suppress
*/
public object FfiConverterTypeLabelParseReport: FfiConverterRustBuffer<LabelParseReport> {
override fun read(buf: ByteBuffer): LabelParseReport {
return LabelParseReport(
FfiConverterUInt.read(buf),
FfiConverterUInt.read(buf),
)
}

override fun allocationSize(value: LabelParseReport) = (
FfiConverterUInt.allocationSize(value.`imported`) +
FfiConverterUInt.allocationSize(value.`skipped`)
)

override fun write(value: LabelParseReport, buf: ByteBuffer) {
FfiConverterUInt.write(value.`imported`, buf)
FfiConverterUInt.write(value.`skipped`, buf)
}
}



data class LoadedCloudBackupDetail (
var `detail`: CloudBackupDetail
,
Expand Down
48 changes: 35 additions & 13 deletions ios/Cove/Flows/SelectedWalletFlow/SelectedWalletScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -368,14 +368,24 @@ struct SelectedWalletScreen: View {
do {
let file = try result.get()
let fileContents = try FileReader(for: file).read()
try labelManager.import(jsonl: fileContents)

app.alertState = .init(
.general(
title: "Success!",
message: "Labels have been imported successfully."
let result = try labelManager.import(jsonl: fileContents)

if result.skipped > 0 {
let noun = result.skipped == 1 ? "label" : "labels"
app.alertState = .init(
.general(
title: "Labels Imported",
message: "Could not import \(result.skipped) \(noun)"
)
)
)
} else {
app.alertState = .init(
.general(
title: "Success!",
message: "Labels have been imported successfully."
)
)
}
Comment thread
praveenperera marked this conversation as resolved.

// when labels are imported, we need to get the transactions again with the updated labels
Task { await manager.rust.getTransactions() }
Expand Down Expand Up @@ -448,13 +458,25 @@ struct SelectedWalletScreen: View {
}

do {
try labelManager.importLabels(labels: labels)
app.alertState = .init(
.general(
title: "Success!",
message: "Labels have been imported successfully."
let result = try labelManager.importLabels(labels: labels)
if result.skipped > 0 {
let noun = result.skipped == 1 ? "label" : "labels"
app.alertState = .init(
.general(
title: "Labels Imported",
message: "Could not import \(result.skipped) \(noun)"
)
)
)
} else {
app.alertState = .init(
.general(
title: "Success!",
message: "Labels have been imported successfully."
)
Comment thread
Sandipmandal25 marked this conversation as resolved.
)
}

Task { await manager.rust.getTransactions() }

} catch {
app.alertState = .init(
Expand Down
25 changes: 22 additions & 3 deletions ios/Cove/ScanManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,16 @@ import SwiftUI
return setInvalidLabels()
}

try LabelManager(id: selectedWallet).import(labels: labels)
app.alertState = .init(.importedLabelsSuccessfully)
let report = try LabelManager(id: selectedWallet).import(labels: labels)
if report.skipped > 0 {
let noun = report.skipped == 1 ? "label" : "labels"
app.alertState = .init(.general(
title: "Labels Imported",
message: "Could not import \(report.skipped) \(noun)"
))
Comment thread
Sandipmandal25 marked this conversation as resolved.
} else {
app.alertState = .init(.importedLabelsSuccessfully)
}
Task { await manager.rust.getTransactions() }
}
} catch {
Expand Down Expand Up @@ -97,7 +105,18 @@ import SwiftUI
Log.error(panic)
case let .bip329Labels(labels):
if let selectedWallet = Database().globalConfig().selectedWallet() {
return try LabelManager(id: selectedWallet).import(labels: labels)
let report = try LabelManager(id: selectedWallet).import(labels: labels)
if report.skipped > 0 {
let noun = report.skipped == 1 ? "label" : "labels"
app.alertState = TaggedItem(.general(
title: "Labels Imported",
message: "Could not import \(report.skipped) \(noun)"
))
} else {
app.alertState = TaggedItem(.importedLabelsSuccessfully)
}
Task { await app.walletManager?.rust.getTransactions() }
return
}

app.alertState = TaggedItem(
Expand Down
2 changes: 1 addition & 1 deletion ios/CoveCore/Sources/CoveCore/CoveCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public extension FiatOrBtc {
}

public extension LabelManager {
func `import`(labels: Bip329Labels) throws {
func `import`(labels: Bip329Labels) throws -> LabelParseReport {
try importLabels(labels: labels)
}
}
Expand Down
Loading
Loading