Add shared block explorer presets#795
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR adds a curated list of block explorer presets (mempool.space, mempool.guide, Bull Bitcoin, Blockstream, Custom) shared across iOS and Android via UniFFI. It also refactors the template parsing into a dedicated module, adds scheme inference for local/IP addresses, and updates the settings UI to show a picker before the custom URL editor.
Confidence Score: 5/5Safe to merge; the two findings are cosmetic UX nits that don't affect data integrity or stored state. The Rust core changes are well-tested, the UniFFI surface is consistent with existing patterns, and no stored data is at risk. The two flagged issues — unconditional input clearing when re-tapping an already-selected Custom option, and synchronous DB calls in savePreset on the main thread — are both minor quality concerns that don't cause incorrect persisted state or crashes. The select(.custom) path in both BlockExplorerSettingsView.swift and BlockExplorerSettingsScreen.kt clears the text field even when Custom is already the active selection. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant UI as Settings UI (iOS/Android)
participant Rust as Rust (UniFFI)
participant DB as Database
Note over UI,DB: Selecting a preset (non-Custom)
UI->>Rust: setBlockExplorerOption(network, option)
Rust->>DB: clear OR set custom template
DB-->>Rust: ok
Rust-->>UI: normalized template string?
UI->>Rust: effectiveBlockExplorerPreview(network)
Rust-->>UI: preview URL
UI->>Rust: selectedBlockExplorerOption(network)
Rust-->>UI: BlockExplorerOption
Note over UI,DB: Selecting Custom (local state only, no DB write)
UI->>UI: "selectedOption = .custom, input = """
Note over UI,DB: Saving a custom URL
UI->>Rust: setCustomBlockExplorer(network, input)
Rust->>DB: store template
DB-->>Rust: ok
Rust-->>UI: normalized template
UI->>Rust: effectiveBlockExplorerPreview(network)
Rust-->>UI: preview URL
UI->>Rust: selectedBlockExplorerOption(network)
Rust-->>UI: BlockExplorerOption (.custom)
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant UI as Settings UI (iOS/Android)
participant Rust as Rust (UniFFI)
participant DB as Database
Note over UI,DB: Selecting a preset (non-Custom)
UI->>Rust: setBlockExplorerOption(network, option)
Rust->>DB: clear OR set custom template
DB-->>Rust: ok
Rust-->>UI: normalized template string?
UI->>Rust: effectiveBlockExplorerPreview(network)
Rust-->>UI: preview URL
UI->>Rust: selectedBlockExplorerOption(network)
Rust-->>UI: BlockExplorerOption
Note over UI,DB: Selecting Custom (local state only, no DB write)
UI->>UI: "selectedOption = .custom, input = """
Note over UI,DB: Saving a custom URL
UI->>Rust: setCustomBlockExplorer(network, input)
Rust->>DB: store template
DB-->>Rust: ok
Rust-->>UI: normalized template
UI->>Rust: effectiveBlockExplorerPreview(network)
Rust-->>UI: preview URL
UI->>Rust: selectedBlockExplorerOption(network)
Rust-->>UI: BlockExplorerOption (.custom)
Reviews (2): Last reviewed commit: "Match preset block explorers explicitly" | Re-trigger Greptile |
b345da9 to
de9d0ea
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/BlockExplorerSettingsScreen.kt`:
- Around line 131-134: The block explorer persistence call in
BlockExplorerSettingsScreen should stay on the caller coroutine thread instead
of hopping to Dispatchers.IO. Update the logic around
config.setCustomBlockExplorer inside the relevant save flow to invoke the Rust
FFI call directly, and keep the surrounding coroutine handling unchanged so the
function still captures the returned result normally.
- Around line 170-176: The selectOption function in BlockExplorerSettingsScreen
should not reset the custom explorer input when CUSTOM is tapped while it is
already selected. Update the BlockExplorerOption.CUSTOM branch in selectOption
to return early if selectedOption is already CUSTOM, so the existing input and
preview remain unchanged; otherwise keep the existing behavior for switching to
CUSTOM.
In
`@android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt`:
- Around line 136-138: The early return in the node selection handler is
comparing only selectedNodeName, which can incorrectly block a real change when
a custom node shares a name with a preset. Update the guard in
NodeSettingsScreen’s selection logic to compare the actual selected node state,
using both selectedNodeName and selectedNodeSelection (or the full selection
identity) before returning, so a preset can still be selected when the name
matches but the selection type differs.
In `@ios/Cove/Flows/SettingsFlow/BlockExplorerSettingsView.swift`:
- Around line 123-128: The select(_:) handler in BlockExplorerSettingsView is
clearing the custom editor even when .custom is already selected. Update the
BlockExplorerOption switching logic to return early if the tapped option matches
the current selectedOption, and only reset input/updatePreview when changing
into the custom option from a different selection. Keep the fix localized to
select(_:) so saved custom templates are preserved when re-tapping the Custom
row.
In `@rust/src/custom_block_explorer.rs`:
- Around line 73-80: The default label returned by as_display_name is
provider-specific, but MempoolSpace is only the default option and may not map
to mempool.space on all networks. Update the MempoolSpace match arm in
custom_block_explorer::as_display_name to use a provider-neutral label such as
“Default explorer”, or make it network-aware if the display name should reflect
the active template.
In `@rust/src/custom_block_explorer/template.rs`:
- Around line 326-333: The known_host_network_prefix mapping in template.rs only
handles mempool.space and mutinynet.com, so BlockExplorerOption::base_url() ->
from_base_url() can drop the network segment for new multi-network presets like
Blockstream on Testnet. Extend the prefix table to cover provider-specific
non-Bitcoin network prefixes for the new presets, or make unsupported
preset/network combinations fail explicitly in the same flow, and add tests that
verify non-Bitcoin canonicalization for the affected BlockExplorerOption
variants.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: cf6fb8f8-8d01-45f8-bdc8-04252ce7ece2
⛔ Files ignored due to path filters (2)
android/app/src/main/java/org/bitcoinppl/cove_core/cove.ktis excluded by!android/app/src/main/java/org/bitcoinppl/cove_core/**ios/CoveCore/Sources/CoveCore/generated/cove.swiftis excluded by!**/generated/**,!ios/CoveCore/Sources/CoveCore/generated/**
📒 Files selected for processing (12)
.github/workflows/ci.ymlandroid/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/BlockExplorerSettingsScreen.ktandroid/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/MainSettingsScreen.ktandroid/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.ktandroid/app/src/main/res/values/strings.xmlios/Cove/Flows/SettingsFlow/BlockExplorerSettingsView.swiftios/Cove/Flows/SettingsFlow/MainSettingsScreen.swiftios/Cove/Info.plistios/Cove/Views/MiddlePopupView.swiftrust/src/custom_block_explorer.rsrust/src/custom_block_explorer/template.rsrust/src/database/global_config.rs
💤 Files with no reviewable changes (1)
- android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/MainSettingsScreen.kt
Add top-level Cargo environment variables to the CI workflow: CARGO_HTTP_MULTIPLEXING=false and CARGO_NET_RETRY=10. These apply to all jobs to disable HTTP multiplexing and increase retry attempts for Cargo network operations, reducing intermittent CI failures due to registry/network issues.
Show a heading above the block explorer description on both platforms for clarity. Android: wrap the description in a Column and add stringResource(R.string.title_settings_block_explorer) with bodyMedium styling and spacing (BlockExplorerSettingsScreen.kt). iOS: add a VStack containing a "Block Explorer" subheadline (semibold) above the explanatory footnote and adjust spacing (BlockExplorerSettingsView.swift).
Resolve known explorer domains and /tx paths to their canonical templates before the generic fallback. Keep successful custom saves on the Custom row so the normalized template remains visible.
Add async save-state feedback in Android and iOS block explorer settings and default scheme handling for local and IP hosts in URL parsing so custom block explorers save and parse correctly.
Split custom explorer template parsing and validation into a a dedicated module so public option logic stays focused. Keep template behavior intact while centralizing placeholder normalization, URL matching, and stored-template fallback
Android: avoid resetting custom node fields when re-selecting the currently selected preset node by returning early if the node name is unchanged. iOS: add client-side validation and user feedback when saving custom block explorer URLs. Introduce showInvalidUrlAlert and an alert UI, call previewCustomBlockExplorer before saving to catch errors early, simplify isSaving handling with defer, and show success popup on save. Validation errors now surface via an alert. Rust: strengthen URL/host validation for custom block explorer templates. Add validate_host, validate_domain_host, and is_valid_domain_label to enforce domain label rules, allow localhost and numeric IPs, and reject invalid TLDs; update scheme preference logic to treat localhost and .local appropriately. Extend tests to cover local, IP, and invalid domain cases.
Add a pre-save network check for custom block explorer URLs by requesting a known transaction URL first, then persist only on success and present loading/success/error feedback while the check runs
Remove the specialized effectiveBlockExplorerHost API and associated UniFFI bindings/checksum entries, and centralize block-explorer validation in the core. UI changes (Android & iOS) drop the async URL-checking task and related helpers, instead relying on config.setCustomBlockExplorer/preview to validate and produce normalized values; preview and validationError handling were simplified to surface errors while typing. Rust code cleans up documentation comments and removes the GlobalConfigTable host-extraction helper. Note: UniFFI checksum constants were updated — clean/rebuild native bindings after applying this change.
Remove the inline validationError state and its on-screen text. Introduce showUpdateFailedAlert and an alert UI for update failures, and wire error paths to present this alert (while keeping the existing invalid-URL alert). Update error handling in save/update/clear flows to set the new alert flag instead of storing validationError.
Replace the catch-all '_' arm with explicit arms for BlockExplorerOption::MempoolGuide, ::BullBitcoin and ::Blockstream. These variants now use their preset base_url and are registered via set_custom_block_explorer, making the match handling clearer and avoiding a generic wildcard branch.
Preserve custom block explorer input when reselecting the custom option, keep Rust FFI persistence on the caller coroutine, and avoid blocking preset node changes when a custom node shares the same name. Store preset block explorer templates through their network-aware canonical form so non-Bitcoin paths are preserved and unsupported preset networks fail explicitly.
6468cc6 to
0e6f89b
Compare
Summary
Validation
Summary by CodeRabbit
New Features
Bug Fixes
UI Improvements