app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 34f52b9c63960736c6474439f3d91050b70345d7
parent 0cb6b1bb232f037313544d0807d3a4eb737a461f
Author: triesap <tyson@radroots.org>
Date:   Sun, 22 Mar 2026 16:26:37 +0000

web: add browser signer account roster

- expose the connected browser signer through the shared roster summary contract
- keep browser signer custody explicit in the home account list
- reject unknown account selection requests instead of silently switching state
- preserve existing web disconnect and geocoder behavior under the new roster model

Diffstat:
Mcrates/web/src/lib.rs | 42+++++++++++++++++++++++++++++++++++++-----
1 file changed, 37 insertions(+), 5 deletions(-)

diff --git a/crates/web/src/lib.rs b/crates/web/src/lib.rs @@ -17,11 +17,11 @@ use nostr::signer::NostrSigner; use nostr_browser_signer::{BrowserSigner, Error as BrowserSignerError}; #[cfg(target_arch = "wasm32")] use radroots_app_core::{ - HomeActionKind, HomeActionResult, HomeActionState, IdentityGateState, RadrootsApp, - RadrootsAppBackend, RadrootsLocationCountry, RadrootsLocationCountryCenterLookupResult, - RadrootsLocationCountryListResult, RadrootsLocationPoint, RadrootsLocationResolverError, - RadrootsLocationReverseOptions, RadrootsResolvedLocation, RadrootsReverseLocationLookupResult, - SetupActionState, + HomeActionKind, HomeActionResult, HomeActionState, IdentityGateState, RadrootsAccountCustody, + RadrootsAccountSummary, RadrootsApp, RadrootsAppBackend, RadrootsLocationCountry, + RadrootsLocationCountryCenterLookupResult, RadrootsLocationCountryListResult, + RadrootsLocationPoint, RadrootsLocationResolverError, RadrootsLocationReverseOptions, + RadrootsResolvedLocation, RadrootsReverseLocationLookupResult, SetupActionState, }; #[cfg(any(target_arch = "wasm32", test))] use radroots_app_core::{ @@ -260,7 +260,15 @@ impl WebBackend { let _ = &connected.signer; IdentityGateState::Ready { account_id: connected.account_id.clone(), + } + } + + fn account_summary_for_ready(connected: &ConnectedSigner) -> RadrootsAccountSummary { + RadrootsAccountSummary { + account_id: connected.account_id.clone(), npub: connected.npub.clone(), + label: Some("browser signer".to_owned()), + custody: RadrootsAccountCustody::BrowserSigner, } } @@ -334,6 +342,16 @@ impl RadrootsAppBackend for WebBackend { } } + fn load_account_roster(&self) -> Result<Vec<RadrootsAccountSummary>, String> { + let state = self.state.borrow(); + match &state.connection { + WebConnectionState::Ready(connected) => { + Ok(vec![Self::account_summary_for_ready(connected)]) + } + WebConnectionState::Disconnected | WebConnectionState::Connecting => Ok(Vec::new()), + } + } + fn offline_geocoder_state(&self) -> Option<RadrootsOfflineGeocoderState> { Some(self.state.borrow().offline_geocoder_state.clone()) } @@ -575,6 +593,20 @@ impl RadrootsAppBackend for WebBackend { } } + fn request_select_account( + &self, + account_id: &str, + ) -> Result<Option<IdentityGateState>, String> { + let state = self.state.borrow(); + match &state.connection { + WebConnectionState::Ready(connected) if connected.account_id == account_id => { + Ok(Some(Self::identity_state_for_ready(connected))) + } + WebConnectionState::Ready(_) => Err("unknown browser signer account".to_owned()), + WebConnectionState::Disconnected | WebConnectionState::Connecting => Ok(None), + } + } + fn poll_identity_state(&self) -> Result<Option<IdentityGateState>, String> { let mut state = self.state.borrow_mut(); let Some(result) = state.pending_result.take() else {