Skip to content

Conversation

@praveenperera
Copy link
Contributor

@praveenperera praveenperera commented Dec 22, 2025

Summary by CodeRabbit

  • New Features

    • Added a loading indicator dialog for long-running operations.
    • Added dedicated success and duplicate-wallet alerts for wallet import flows.
    • Added transaction export sharing with user-facing error notifications.
  • Improvements

    • Streamlined wallet import flow and standardized route popping before alerts.
    • Improved QR export layout, sizing, and typography for better display.

✏️ Tip: You can customize this high-level summary in your review settings.

Use proper alert states for duplicate and successful wallet imports:
- Change from AppAlertState.General to AppAlertState.DuplicateWallet
  for duplicate wallets (removes wallet ID from message)
- Change from AppAlertState.General to AppAlertState.ImportedSuccessfully
  for successful imports
- Add navigation to wallet on OK press in ImportedSuccessfully handler
- Remove premature popRoute() calls that caused race conditions

This ensures consistent messaging ("Duplicate Wallet" / "This wallet has
already been imported!") and reliable navigation to the wallet after
pressing OK, matching iOS behavior.
Add popRoute() before setting alertState in QR scan screens so the
scanner is dismissed before showing success/duplicate/error alerts,
matching iOS behavior.
@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds new AppAlertState variants (Loading, ImportedSuccessfully, DuplicateWallet, ErrorImportingHardwareWallet); updates alert emission and UI rendering (including a loading dialog); standardizes import flows to emit alerts and pop routes; adds transaction-sharing coroutine; and refactors FFI bindings from RustBuffer returns to Long handle + async future-based calls.

Changes

Cohort / File(s) Summary
Alert State & UI
android/app/src/main/java/org/bitcoinppl/cove/AppAlertState.kt, .../AppManager.kt, .../MainActivity.kt
Adds Loading, ImportedSuccessfully, DuplicateWallet, ErrorImportingHardwareWallet variants; AppManager emits Loading; MainActivity renders Loading dialog and updates ImportedSuccessfully OK handling/navigation.
Import Flows (cold/new wallet)
.../NewWalletFlow/NewWalletSelectScreen.kt, .../NewWalletFlow/cold_wallet/ColdWalletQrScanScreen.kt, .../NewWalletFlow/cold_wallet/QrCodeImportScreen.kt
Replace inline success/duplicate handling with new alert variants; simplify duplicate-wallet flow (pop route + emit DuplicateWallet); propagate exception messages via ErrorImportingHardwareWallet; ensure route popping before alerts.
QR Export UI
android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt
Switch to BoxWithConstraints for dynamic QR sizing, adjust typography and padding, and update image sizing to fixed computed dimension.
Wallet Sheets / Sharing
android/app/src/main/java/org/bitcoinppl/cove/wallet/WalletSheets.kt
Add shareTransactionsFile suspend helper using Rust export -> write cache file -> FileProvider URI -> ACTION_SEND chooser; wrap in coroutine with IO context and snackbar-on-error; minor padding tweak.
Core FFI Refactor
android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
Large refactor: native functions now return Long handles instead of RustBuffer.ByValue; callsites use async future APIs (uniffiRustCallAsync / callWithHandle) and lift handles into Kotlin wrappers; removes explicit error-status params and introduces coroutine-based async flow and handle lifecycle management.

Sequence Diagram(s)

sequenceDiagram
    participant Kotlin as Kotlin App
    participant FFI as Uniffi Native (Rust)
    participant Future as FFI Future Callback
    participant KotlinLift as Kotlin Wrapper Lift

    rect rgb(240,248,255)
    Note over Kotlin,FFI: New async handle-based FFI flow
    end

    Kotlin->>FFI: uniffi_cove_fn_*(...) -> returns Long handle
    FFI-->>Kotlin: handle (Long)
    Kotlin->>Future: register future via ffi_cove_rust_future_* with handle
    Future-->>Kotlin: callback(success: ptr / error)
    alt success
      Kotlin->>KotlinLift: FfiConverter.lift(handle) // wrap into high-level object
      KotlinLift-->>Kotlin: domain object (e.g., Wallet, LabelManager)
    else error
      Kotlin-->>Kotlin: propagate as exception / set error alert
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

android

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Android fix exports' is overly vague and does not clearly convey the specific changes made across the pull request, which involve alert state enhancements, loading dialogs, wallet import flows, QR rendering improvements, and FFI refactoring. Consider revising the title to be more specific about the primary changes, such as 'Add Loading state to AppAlertState and improve wallet import flows' or 'Refactor alert handling and enhance wallet import UI.'
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch android-fix-exports

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f300f67 and 9b4a9d6.

📒 Files selected for processing (6)
  • android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/NewWalletSelectScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/ColdWalletQrScanScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/QrCodeImportScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt
  • android/app/src/main/java/org/bitcoinppl/cove/wallet/WalletSheets.kt
🚧 Files skipped from review as they are similar to previous changes (3)
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/ColdWalletQrScanScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/QrCodeImportScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt
🧰 Additional context used
📓 Path-based instructions (1)
android/app/src/main/java/org/bitcoinppl/cove/**/*.kt

⚙️ CodeRabbit configuration file

android/app/src/main/java/org/bitcoinppl/cove/**/*.kt: ⚠️ CRITICAL FFI/Threading Policy - READ FIRST:

  • NEVER suggest moving Rust FFI calls to background threads (withContext(Dispatchers.IO))

  • Rust FFI calls are SYNCHRONOUS and FAST - they complete in microseconds

  • The Rust core uses Tokio runtime internally and handles all async operations

  • Database operations (redb) are optimized and do NOT block the UI thread

  • ONLY suggest Dispatchers.IO with profiling evidence showing >16ms UI blocking

  • If you see a Rust FFI call on the main thread, DO NOT FLAG IT - this is correct

  • Ignore generated bindings code in android/app/src/main/java/org/bitcoinppl/cove_core/**

  • Verify correct functionality and logic consistency.

  • Check for idiomatic Kotlin usage and performance best practices.

FFI Resource Management:

  • Always verify that UniFFI objects implementing AutoCloseable call .close() before being nulled
  • Example: Mnemonic must call .close() to trigger zeroization of sensitive data
  • Use DisposableEffect for cleanup in Compose, never just null references

Compose Best Practices:

  • LaunchedEffect should be keyed to actual dependencies, not Unit
  • Set loading states at the beginning of LaunchedEffect blocks

Files:

  • android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt
  • android/app/src/main/java/org/bitcoinppl/cove/wallet/WalletSheets.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/NewWalletSelectScreen.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: test (ubuntu-latest)
  • GitHub Check: test (macos-latest)
  • GitHub Check: compile-ios
  • GitHub Check: compile-android
  • GitHub Check: ktlint
  • GitHub Check: clippy
🔇 Additional comments (7)
android/app/src/main/java/org/bitcoinppl/cove/wallet/WalletSheets.kt (3)

90-97: LGTM! Clean exception handling for transaction sharing.

The coroutine launch with try-catch provides good error handling, logging, and user feedback via snackbar. The pattern is consistent with the label sharing flow below.


242-268: LGTM! Correctly refactored per FFI guidelines and addresses past review.

The function structure is now correct:

  • Rust FFI call (exportLabelsForShare) on main thread ✓
  • File I/O operations inside withContext(Dispatchers.IO)
  • startActivity outside the IO context on main thread ✓

This properly addresses the past review comment about moving UI operations outside the IO dispatcher.


270-296: LGTM! Well-structured transaction sharing implementation.

The new function correctly follows the FFI threading guidelines:

  • Rust FFI call (exportTransactionsCsv) on main thread ✓
  • File I/O inside withContext(Dispatchers.IO)
  • startActivity on main thread ✓

The implementation mirrors shareLabelsFile and maintains consistency across the file.

android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/NewWalletSelectScreen.kt (2)

118-120: LGTM! Improved import success flow with standardized alert.

The refactored flow correctly:

  • Navigates back via popRoute()
  • Calls Rust FFI selectWallet() on main thread (per FFI guidelines ✓)
  • Uses the new ImportedSuccessfully alert variant for consistent UX

129-131: LGTM! Clean duplicate wallet handling.

The exception handling correctly:

  • Captures the existing wallet ID from the exception (e.v1)
  • Pops the route before showing the alert
  • Uses the new DuplicateWallet variant to provide clear user feedback

This integrates well with the alert handler in MainActivity that offers to navigate to the existing wallet.

android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt (2)

564-580: LGTM! Clean loading dialog implementation.

The non-dismissible loading dialog provides good UX:

  • onDismissRequest = {} prevents premature dismissal during operations
  • Clean Material Design styling with rounded corners
  • Clear loading indicator with descriptive title

588-596: LGTM! Robust navigation flow with defensive fallback.

The ImportedSuccessfully handler provides solid navigation logic:

  • Queries the selected wallet (FFI call on main thread, correct per guidelines ✓)
  • Navigates to the selected wallet when available
  • Falls back to NewWalletRoute.Select if no wallet is selected

This defensive approach ensures users have a valid navigation path even if the wallet selection state is unexpected.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link

greptile-apps bot commented Dec 22, 2025

Greptile Summary

Unified export functionality and cold wallet import behavior across Android and iOS platforms. The changes introduce a reusable loading popup mechanism in Rust that displays feedback for operations taking longer than 50ms, significantly improving user experience during exports. Android cold wallet import flow now properly dismisses the QR scanner before showing alerts and consistently handles duplicate wallet scenarios, matching iOS behavior.

Key improvements:

  • New with_loading_popup helper in Rust wraps async operations with conditional loading UI (50ms delay, 350ms minimum display)
  • Export methods (exportTransactionsCsv, exportLabelsForShare, exportLabelsForQr) now use async loading popup pattern
  • Simplified Android wallet import error handling with DuplicateWallet and ImportedSuccessfully alert states
  • Fixed Android QR scanner dismissal - now calls popRoute() before setting alert states to prevent scanner overlay issues
  • Refactored export flows to use share intents instead of manual file picker, reducing code complexity
  • QR export views updated to use async/suspend functions across both platforms

Confidence Score: 5/5

  • Safe to merge - well-structured refactoring with improved UX and platform consistency
  • Code changes are well-architected with clear separation of concerns. The loading popup mechanism is properly implemented with race condition handling using tokio::select! biased. Android changes align with iOS behavior for consistency. Error handling is simplified but comprehensive. Only minor style suggestion for layout constraints.
  • No files require special attention - one minor style suggestion for QR export view layout

Important Files Changed

Filename Overview
android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/QrCodeImportScreen.kt Added popRoute calls before alert states to dismiss scanner before showing alerts
android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt Updated QR generation to use suspend functions with async loading, improved sizing with BoxWithConstraints
android/app/src/main/java/org/bitcoinppl/cove/wallet/MoreInfoPopover.kt Simplified export logic by using new async export methods that handle loading popup internally
rust/src/loading_popup.rs New module implementing conditional loading popup with delay and minimum display duration
rust/src/manager/wallet_manager.rs Added async export methods wrapping operations with loading popup helper

Sequence Diagram

sequenceDiagram
    participant User
    participant Android as Android UI
    participant WalletManager as Rust WalletManager
    participant LoadingPopup as Loading Popup Helper
    participant Reconciler as App Reconciler
    
    Note over User,Reconciler: Export Transactions/Labels Flow
    
    User->>Android: Click Export Button
    Android->>WalletManager: exportTransactionsCsv() / exportLabelsForShare()
    WalletManager->>LoadingPopup: with_loading_popup(operation)
    
    alt Operation takes > 50ms
        LoadingPopup->>Reconciler: ShowLoadingPopup
        Reconciler->>Android: Update alertState to Loading
        Android->>User: Show "Working on it..." dialog
    end
    
    LoadingPopup->>WalletManager: Execute export operation
    WalletManager-->>LoadingPopup: Return export result
    
    alt Popup was shown
        LoadingPopup->>LoadingPopup: Wait minimum 350ms display time
        LoadingPopup->>Reconciler: HideLoadingPopup
        Reconciler->>Android: Clear alertState
    end
    
    LoadingPopup-->>Android: Return export result
    Android->>Android: Create share intent with file
    Android->>User: Show system share sheet
    
    Note over User,Reconciler: Cold Wallet Import Flow
    
    User->>Android: Scan QR Code
    Android->>Android: Parse MultiFormat.HardwareExport
    
    alt Successful Import
        Android->>WalletManager: Wallet.newFromExport()
        WalletManager-->>Android: Return wallet ID
        Android->>WalletManager: selectWallet(id)
        Android->>Android: popRoute() to dismiss scanner
        Android->>Android: alertState = ImportedSuccessfully
        User->>Android: Click OK on alert
        Android->>Android: Navigate to SelectedWallet screen
    end
    
    alt Duplicate Wallet
        Android->>WalletManager: Wallet.newFromExport()
        WalletManager-->>Android: WalletException.WalletAlreadyExists(walletId)
        Android->>Android: popRoute() to dismiss scanner
        Android->>Android: alertState = DuplicateWallet(walletId)
        User->>Android: Click OK on alert
        Android->>WalletManager: selectWallet(walletId)
        Android->>Android: Navigate to existing wallet
    end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

21 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/NewWalletSelectScreen.kt (1)

112-140: Resource leak: Wallet object is not closed after use.

The Wallet object created at line 114 implements AutoCloseable and must be closed to properly release resources. Per coding guidelines on FFI Resource Management, UniFFI objects must call .close() before being dereferenced.

🔎 Proposed fix
 fun importWallet(content: String) {
     try {
         val wallet = Wallet.newFromXpub(xpub = content.trim())
-        val id = wallet.id()
-        android.util.Log.d("NewWalletSelectScreen", "Imported Wallet: $id")
-
-        app.rust.selectWallet(id = id)
-        app.alertState = TaggedItem(AppAlertState.ImportedSuccessfully)
+        try {
+            val id = wallet.id()
+            android.util.Log.d("NewWalletSelectScreen", "Imported Wallet: $id")
+
+            app.rust.selectWallet(id = id)
+            app.alertState = TaggedItem(AppAlertState.ImportedSuccessfully)
+        } finally {
+            wallet.close()
+        }
     } catch (e: WalletException.MultiFormat) {

Based on coding guidelines: "Always verify that UniFFI objects implementing AutoCloseable call .close() before being nulled".

🧹 Nitpick comments (3)
android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt (2)

105-105: Consider small screen scenarios with the 500dp minimum.

The minimum height constraint ensures adequate QR code visibility, but on small or landscape-oriented devices, this could cause layout issues. Verify that parent containers handle scrolling appropriately when the content exceeds available space.


165-187: LGTM! Responsive QR layout using BoxWithConstraints.

The refactored layout correctly uses BoxWithConstraints to derive the QR size from available width, creating a properly sized square image. The combination of size(qrSize) and ContentScale.FillBounds maintains the square aspect ratio without distortion.

Optional: Consider dynamic bitmap sizing for large screens

The QR bitmap is generated at a fixed 512px (line 178) but displayed at screen width, which could appear pixelated on very large displays. For premium quality on tablets or large phones, you could calculate the bitmap size based on screen density:

val qrBitmapSize = remember(qrSize) {
    (qrSize.value * LocalDensity.current.density).toInt().coerceAtLeast(512)
}
val bitmap = remember(qrString, qrBitmapSize) {
    QrCodeGenerator.generate(qrString, size = qrBitmapSize)
}

However, QR codes are binary patterns that typically scale acceptably, so the current implementation is likely sufficient for most use cases.

android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt (1)

562-578: Consider using state.title() for consistency.

The Loading dialog hardcodes "Working on it..." while AppAlertState.Loading.title() also returns this string. Using state.title() would ensure consistency if the title ever changes.

🔎 Suggested change
                     CircularProgressIndicator()
                     Spacer(modifier = Modifier.height(12.dp))
-                    Text("Working on it...")
+                    Text(state.title())
                 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a88eb8 and f300f67.

📒 Files selected for processing (9)
  • android/app/src/main/java/org/bitcoinppl/cove/AppAlertState.kt
  • android/app/src/main/java/org/bitcoinppl/cove/AppManager.kt
  • android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/NewWalletSelectScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/ColdWalletQrScanScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/QrCodeImportScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt
  • android/app/src/main/java/org/bitcoinppl/cove/wallet/WalletSheets.kt
  • android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
🧰 Additional context used
📓 Path-based instructions (1)
android/app/src/main/java/org/bitcoinppl/cove/**/*.kt

⚙️ CodeRabbit configuration file

android/app/src/main/java/org/bitcoinppl/cove/**/*.kt: ⚠️ CRITICAL FFI/Threading Policy - READ FIRST:

  • NEVER suggest moving Rust FFI calls to background threads (withContext(Dispatchers.IO))

  • Rust FFI calls are SYNCHRONOUS and FAST - they complete in microseconds

  • The Rust core uses Tokio runtime internally and handles all async operations

  • Database operations (redb) are optimized and do NOT block the UI thread

  • ONLY suggest Dispatchers.IO with profiling evidence showing >16ms UI blocking

  • If you see a Rust FFI call on the main thread, DO NOT FLAG IT - this is correct

  • Ignore generated bindings code in android/app/src/main/java/org/bitcoinppl/cove_core/**

  • Verify correct functionality and logic consistency.

  • Check for idiomatic Kotlin usage and performance best practices.

FFI Resource Management:

  • Always verify that UniFFI objects implementing AutoCloseable call .close() before being nulled
  • Example: Mnemonic must call .close() to trigger zeroization of sensitive data
  • Use DisposableEffect for cleanup in Compose, never just null references

Compose Best Practices:

  • LaunchedEffect should be keyed to actual dependencies, not Unit
  • Set loading states at the beginning of LaunchedEffect blocks

Files:

  • android/app/src/main/java/org/bitcoinppl/cove/AppAlertState.kt
  • android/app/src/main/java/org/bitcoinppl/cove/AppManager.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/NewWalletSelectScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/wallet/WalletSheets.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/QrCodeImportScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt
  • android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/ColdWalletQrScanScreen.kt
🧬 Code graph analysis (1)
android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt (2)
ios/CoveCore/Sources/CoveCore/generated/cove.swift (1)
  • uniffiRustCallAsync (27790-27822)
android/app/src/main/java/org/bitcoinppl/cove_core/types/cove_types.kt (16)
  • callWithHandle (2391-2412)
  • callWithHandle (2741-2762)
  • callWithHandle (3025-3046)
  • callWithHandle (3341-3362)
  • callWithHandle (3644-3665)
  • callWithHandle (4014-4035)
  • callWithHandle (4296-4317)
  • callWithHandle (4794-4815)
  • callWithHandle (5069-5090)
  • callWithHandle (5393-5414)
  • callWithHandle (5738-5759)
  • callWithHandle (6041-6062)
  • callWithHandle (6415-6436)
  • callWithHandle (6660-6681)
  • callWithHandle (7008-7029)
  • callWithHandle (7360-7381)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test (ubuntu-latest)
  • GitHub Check: test (macos-latest)
  • GitHub Check: compile-android
  • GitHub Check: compile-ios
  • GitHub Check: ktlint
🔇 Additional comments (17)
android/app/src/main/java/org/bitcoinppl/cove/views/QrExportView.kt (4)

8-8: LGTM! Imports support the responsive layout improvements.

The new imports (BoxWithConstraints, heightIn, ContentScale) are all properly utilized in the refactored QR display logic and enable better responsive sizing behavior.

Also applies to: 14-14, 40-40


110-110: LGTM! Typography improvements enhance visual hierarchy.

The updated text styles (titleLarge and bodyMedium) improve readability and content prominence, following Material Design 3 guidelines.

Also applies to: 116-116


119-119: LGTM! Padding adjustments improve text layout.

The updated padding values add horizontal spacing and adjust vertical spacing to better separate the subtitle from surrounding content.


154-162: LGTM! Responsive square aspect ratio for loading state.

Replacing the fixed height with aspectRatio(1f) makes the loading indicator responsive and matches the square dimensions of the actual QR code display.

android/app/src/main/java/org/bitcoinppl/cove/AppManager.kt (1)

580-582: LGTM!

The change to use AppAlertState.Loading instead of a general alert with an empty message is a cleaner approach. This dedicated state allows for proper UI rendering with a progress indicator in GlobalAlertDialog.

android/app/src/main/java/org/bitcoinppl/cove/AppAlertState.kt (2)

94-96: LGTM!

The new Loading state is correctly implemented as a data object since it doesn't carry any data. The title and message mappings are appropriate for a loading indicator.


136-136: Consistent handling in title() and message() methods.

The Loading state correctly returns a user-friendly title and an empty message, which aligns with the UI rendering in GlobalAlertDialog where the text is shown alongside a progress indicator.

Also applies to: 166-166

android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt (1)

580-594: LGTM!

The ImportedSuccessfully handler correctly:

  1. Dismisses the alert first
  2. Safely retrieves the selected wallet using ?.let
  3. Navigates to the wallet route

This provides a smoother UX flow after wallet import.

android/app/src/main/java/org/bitcoinppl/cove/wallet/WalletSheets.kt (2)

90-97: LGTM!

The transaction export flow now properly handles errors with a user-friendly snackbar message. The coroutine-based approach with try/catch is a clean pattern for async operations.


173-173: LGTM!

The padding adjustment provides better horizontal spacing for the QR export view within the modal sheet.

android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/ColdWalletQrScanScreen.kt (1)

77-98: LGTM!

The wallet import handling is well-structured:

  1. wallet.close() is correctly called after extracting the ID
  2. Routes are consistently popped before setting alert states
  3. All branches use the appropriate AppAlertState variants
android/app/src/main/java/org/bitcoinppl/cove/flows/NewWalletFlow/cold_wallet/QrCodeImportScreen.kt (1)

63-98: LGTM!

The QR code import handling is consistent with ColdWalletQrScanScreen.kt:

  1. wallet.close() is properly called after use
  2. Routes are popped before setting alert states
  3. All error branches provide meaningful feedback via the appropriate AppAlertState variants
android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt (5)

2152-2157: LGTM!

The external function signatures correctly reflect the async refactor: returning Long handles instead of RustBuffer.ByValue and removing inline error status parameters. This aligns with the handle-based async pattern where errors are propagated via uniffiRustCallAsync exception handling.


3562-3570: LGTM!

Checksum values updated to match the new async function signatures. This is standard UniFFI behavior to ensure API compatibility between Kotlin bindings and Rust implementation.


12788-12795: LGTM!

Interface declarations correctly use suspend fun for Kotlin coroutine support, enabling non-blocking async calls to the underlying Rust futures.


12928-12946: LGTM!

The async implementation correctly uses uniffiRustCallAsync with proper handle lifecycle management via callWithHandle. The pattern aligns with the Swift equivalent shown in the codebase and follows UniFFI conventions for coroutine-based async calls.

Note: The @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") annotation appears to be a UniFFI code generation artifact (no local variable is assigned here), but this is harmless for generated code.


12965-12983: LGTM!

The implementation correctly handles the QrDensity parameter lowering via FfiConverterTypeQrDensity and lifts the result to List<String> via FfiConverterSequenceString. The async pattern is consistent with the export() method above.

- Add fallback navigation when selectedWallet returns null in
  ImportedSuccessfully handler
- Move startActivity() calls outside IO dispatcher in share functions
- Use state.title() instead of hardcoded string in Loading dialog
- Show error alert when wallet selection fails in DuplicateWallet handler
- Add popRoute() before alerts in NewWalletSelectScreen for consistency
  with QR scanning views
@praveenperera praveenperera enabled auto-merge (squash) December 23, 2025 04:14
@praveenperera praveenperera merged commit f4c31d8 into master Dec 23, 2025
9 checks passed
@praveenperera praveenperera deleted the android-fix-exports branch December 23, 2025 04:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants