1
0
forked from GRIN/grim

Build 76: split mixnet vs nostr status; tidy the identity chips

- The profile card drops the duplicate npub line and shows two statuses: the
  mixnet ("Connected over Nym", ~instant) and under it the nostr relay
  ("Connected to nostr" / "Connecting to relays…"). The relay connection is the
  slower step, not the mixnet.
- New cheap cached nym::is_ready() flag backs the mixnet status (no per-frame
  TCP probe), set when the SOCKS5 proxy comes up.
- Sidebar identity chip: smaller handle so the npub stays on one line, with a
  matching Nym/relay status.
This commit is contained in:
2ro
2026-06-14 18:23:00 -04:00
parent fb4f27a88f
commit 8e1b3ce847
3 changed files with 39 additions and 26 deletions
+26 -25
View File
@@ -631,18 +631,21 @@ impl GoblinWalletView {
w::avatar_any(ui, &handle, &npub_hex, 36.0, hue, tex.as_ref());
ui.add_space(10.0);
ui.vertical(|ui| {
// Smaller so the npub/handle stays on one line.
ui.label(
RichText::new(&handle)
.font(FontId::new(14.0, fonts::semibold()))
.font(FontId::new(12.0, fonts::semibold()))
.color(t.surface_text),
);
ui.label(
RichText::new(if connected {
"synced · Nym"
"Connected over Nym"
} else if crate::nym::is_ready() {
"Nym ready · relays…"
} else {
"connecting…"
"Connecting to Nym"
})
.font(FontId::new(12.0, fonts::regular()))
.font(FontId::new(11.0, fonts::regular()))
.color(t.surface_text_mute),
);
});
@@ -1859,34 +1862,32 @@ impl GoblinWalletView {
.font(FontId::new(17.0, fonts::bold()))
.color(t.surface_text),
);
if !npub.is_empty() {
// Full npub when it fits on one line, else head…tail.
let full = ui.painter().layout_no_wrap(
npub.clone(),
FontId::new(11.0, fonts::mono()),
t.surface_text_mute,
);
let text = if full.size().x <= ui.available_width() {
npub.clone()
} else {
format!("{}{}", &npub[..12], &npub[npub.len() - 6..])
};
ui.label(
RichText::new(text)
.font(FontId::new(11.0, fonts::mono()))
.color(t.surface_text_mute),
);
}
let status = if connected {
// Mixnet status (fast) in place of the redundant second npub line.
let mixnet = if crate::nym::is_ready() {
"Connected over Nym"
} else {
"Connecting…"
"Connecting to Nym"
};
ui.label(
RichText::new(status)
RichText::new(mixnet)
.font(FontId::new(13.0, fonts::regular()))
.color(t.surface_text_dim),
);
// nostr relay status — the slower step (a relay reached over Nym).
let nostr = if connected {
"Connected to nostr"
} else {
"Connecting to relays…"
};
ui.label(
RichText::new(nostr)
.font(FontId::new(12.0, fonts::regular()))
.color(t.surface_text_mute),
);
if !crate::nym::is_ready() || !connected {
ui.ctx()
.request_repaint_after(std::time::Duration::from_millis(600));
}
});
});
if avatar_busy {
+1 -1
View File
@@ -25,7 +25,7 @@ pub mod transport;
use std::time::Duration;
pub use sidecar::warm_up;
pub use sidecar::{is_ready, warm_up};
pub use transport::NymWebSocketTransport;
/// Local SOCKS5 endpoint exposed by the in-process Nym SOCKS5 client.
+12
View File
@@ -21,6 +21,7 @@
use std::net::{SocketAddr, TcpStream};
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::{Duration, Instant};
@@ -44,12 +45,22 @@ pub fn warm_up() {
thread::spawn(|| {
if port_open(Duration::from_millis(300)) {
info!("nym: reusing SOCKS5 endpoint already listening on {SOCKS5_HOST}:{SOCKS5_PORT}");
MIXNET_READY.store(true, Ordering::Relaxed);
return;
}
run_client();
});
}
/// Set once the local mixnet SOCKS5 proxy (:1080) is up and accepting.
static MIXNET_READY: AtomicBool = AtomicBool::new(false);
/// Whether the mixnet proxy is warm. Cheap and cached — safe to poll from the UI
/// each frame, unlike a fresh TCP probe. Distinct from a relay being connected.
pub fn is_ready() -> bool {
MIXNET_READY.load(Ordering::Relaxed)
}
/// True when something accepts TCP on the SOCKS5 port.
fn port_open(timeout: Duration) -> bool {
let addr: SocketAddr = match format!("{SOCKS5_HOST}:{SOCKS5_PORT}").parse() {
@@ -111,6 +122,7 @@ fn run_client() {
started.elapsed().as_millis(),
client.nym_address()
);
MIXNET_READY.store(true, Ordering::Relaxed);
// Hold the client (and thus the SOCKS5 listener + mixnet tasks) open for
// the whole process lifetime; the runtime keeps polling them.
std::future::pending::<()>().await;