pub struct AppHandle { /* private fields */ }Implementations§
Source§impl AppHandle
impl AppHandle
pub async fn start() -> Result<Self>
Sourcepub fn peek_mdns_enabled(master_key: Option<&[u8; 32]>) -> Result<bool>
pub fn peek_mdns_enabled(master_key: Option<&[u8; 32]>) -> Result<bool>
huddle 0.7.8: peek the persisted mdns_enabled setting without
starting the full AppHandle. Called by main.rs before
start_with_options so the initial NetworkMode reflects the
user’s saved preference (the CLI --mode flag, when present,
still wins — main.rs only calls this if --mode is absent).
Returns true if the key is missing (default ON, preserving
pre-0.7.8 behavior).
pub async fn start_with_options( mode: NetworkMode, port: u16, master_key: Option<&[u8; 32]>, relays: Vec<Multiaddr>, server_url: Option<String>, tor_socks: Option<String>, ) -> Result<Self>
pub async fn start_with_db(db: Db) -> Result<Self>
pub async fn start_with_db_and_options( db: Db, mode: NetworkMode, port: u16, session_persist_key: [u8; 32], relays: Vec<Multiaddr>, server_url: Option<String>, tor_socks: Option<String>, ) -> Result<Self>
pub fn mode(&self) -> NetworkMode
Sourcepub fn server_connected(&self) -> bool
pub fn server_connected(&self) -> bool
huddle 0.8: whether the centralized-server connection is currently up. Used by the TUI status line and by tests waiting for connect.
Sourcepub fn server_enabled(&self) -> bool
pub fn server_enabled(&self) -> bool
huddle 0.8: whether a centralized server was configured at startup
(vs --no-server / a None server URL). The TUI uses this to
decide whether to render the relay indicator at all — there’s no
point showing a “disconnected” badge for a feature the user turned
off.
pub fn subscribe(&self) -> Receiver<AppEvent>
pub fn fingerprint(&self) -> &str
pub fn peer_id(&self) -> PeerId
Sourcepub fn sign_invite(&self, invite: InviteLink) -> Result<InviteLink>
pub fn sign_invite(&self, invite: InviteLink) -> Result<InviteLink>
huddle 0.7.11: bind an invite link to our Ed25519 identity by signing it. The receiver re-derives the fingerprint from the embedded pubkey and rejects the invite if any signed field (host_multiaddr, fingerprint, room id/name/encrypted/salt/ creator_fp/owner_list, signed_at_ms) was tampered with.
pub fn discovered_rooms(&self) -> Vec<DiscoveredRoom>
Sourcepub fn dm_partner_fingerprint(&self, room_id: &str) -> Option<String>
pub fn dm_partner_fingerprint(&self, room_id: &str) -> Option<String>
huddle 0.7: returns the fingerprint of the other party in a 1-1
DM. None for rooms that are Group, missing, or somehow have a
non-2-member state. Used by the DM-pane header to render the
partner’s username + HD-ID.
pub fn active_room_ids(&self) -> Vec<String>
pub fn active_room_info(&self, room_id: &str) -> Option<StoredRoom>
pub fn room_members(&self, room_id: &str) -> Vec<String>
pub fn room_messages( &self, room_id: &str, limit: i64, ) -> Result<Vec<StoredRoomMessage>>
pub fn search_room_messages( &self, room_id: &str, query: &str, limit: i64, ) -> Result<Vec<StoredRoomMessage>>
Sourcepub async fn start_room(
&self,
name: &str,
encrypted: bool,
passphrase: Option<&str>,
kind: RoomKind,
) -> Result<String>
pub async fn start_room( &self, name: &str, encrypted: bool, passphrase: Option<&str>, kind: RoomKind, ) -> Result<String>
Create a new room. Returns its room_id.
huddle 0.7: kind is now required. RoomKind::Group (the default)
preserves pre-0.7 behavior. RoomKind::Direct is reserved for
callers that have already computed a deterministic DM room_id via
canonical_dm_room_id — most clients should call start_direct
instead, which handles idempotency, kind, and naming.
Sourcepub async fn start_direct(&self, partner_fingerprint: &str) -> Result<String>
pub async fn start_direct(&self, partner_fingerprint: &str) -> Result<String>
huddle 0.7.1: start (or open) a 1-1 DM with partner_fingerprint.
Idempotent across peers and reopens:
- Refuses to DM yourself.
- Computes
room_id = canonical_dm_room_id(our_fp, partner_fp). Both peers, regardless of who clicks first, derive identical IDs. - If a DM room already exists locally (active or stored), returns its id — no new room, no second announcement.
- Otherwise creates a
RoomKind::Direct, end-to-end encrypted room. The key is derived from Ed25519→X25519 ECDH between the two parties’ identity keys (seecrypto::dm::derive_dm_key). No shared passphrase, no central key agreement — both peers independently derive the same 32-byte room key from their own seed + the other’s pubkey. - If we don’t yet know the partner’s Ed25519 pubkey, the room
is still created encrypted; the key is derived lazily once
MemberAnnouncearrives with the partner’s pubkey, after which we send our wrapped Megolm session key in a follow-up announce. - Subscribes to the room topic and announces on the global topic.
The announcement is visibility-filtered at honest 0.7+ peers,
so only the partner sees it in their
discovered_rooms().
Sourcepub async fn join_room(
&self,
room_id: &str,
passphrase: Option<&str>,
) -> Result<()>
pub async fn join_room( &self, room_id: &str, passphrase: Option<&str>, ) -> Result<()>
Join an existing room. The room may come from a live announcement
(preferred), our restorable set, or the DB directly — whichever has
the freshest copy. For encrypted rooms passphrase is required.
Sourcepub async fn leave_room(&self, room_id: &str) -> Result<bool>
pub async fn leave_room(&self, room_id: &str) -> Result<bool>
Leave a room. Returns true when the MemberLeave notice was
handed to the network layer, false when it couldn’t be encoded
(peers then only notice via the discovered-room TTL). The local
leave always succeeds regardless.
pub async fn send_room_message(&self, room_id: &str, body: &str) -> Result<()>
pub async fn shutdown(&self)
Sourcepub async fn dial_by_id_or_username(&self, input: &str) -> Result<()>
pub async fn dial_by_id_or_username(&self, input: &str) -> Result<()>
Dial a peer by a user-entered address. Accepts:
1.2.3.4:9000[fe80::1]:9000/ip4/.../tcp/...[/p2p/<peer>](raw multiaddr) huddle 0.5.1: resolve an HD- ID or username back to a dialable multiaddr and dial it.
input is matched against, in order:
- an
HD-XXXX-...prefixed string → strip prefix + lowercase to canonical fingerprint; - a raw 24-char hex run (with or without dashes) → group into 4-char blocks and lowercase;
- otherwise → treat as a username and look up
peer_profiles.
Resolution to an address: scan discovered_rooms for a room
whose creator_fingerprint matches; take the first host_addrs
entry. Falls back to the known_peers table for users we’ve
dialed before. Both paths require we’ve seen the peer on our
gossipsub mesh or dialed them before — bare-ID dialing on a
cold mesh is fundamentally impossible without a routing layer
huddle deliberately doesn’t run (DHT, central directory). For
cross-internet first contact, paste an invite link instead.
pub async fn dial(&self, input: &str) -> Result<()>
Sourcepub fn nat_reachable_addrs(&self) -> Vec<String>
pub fn nat_reachable_addrs(&self) -> Vec<String>
Phase D follow-up: snapshot of the NAT reachability state. Returns the addresses AutoNAT has confirmed as externally reachable in this session. The lobby renders an emoji badge from this — non-empty ⇒ ‘reachable’, empty ⇒ ‘LAN only’.
Sourcepub fn dialable_addrs(&self) -> Vec<String>
pub fn dialable_addrs(&self) -> Vec<String>
Phase D follow-up: addresses suitable for putting on the wire so other peers can dial us. Union of:
- AutoNAT-confirmed external addresses (direct internet)
- active
/p2p-circuitreservations on configured relays Capped at 4 entries to keep room announcements small. Relay-circuit addresses are listed first (they’re more likely to work for NAT’d peers).
Sourcepub async fn dial_invite(&self, address: &str, claimed_fp: &str) -> Result<()>
pub async fn dial_invite(&self, address: &str, claimed_fp: &str) -> Result<()>
Phase C follow-up: dial a peer whose multiaddr came from an
invite link claiming claimed_fp. Behaves identically to
dial, but additionally stashes (canonical_addr → claimed_fp)
in pending_invite_dials so the PeerIdentified handler can
assert the cryptographic fp matches the human-display one in
the invite. Mismatch ⇒ disconnect + InviteFingerprintMismatch
event.
libp2p’s /p2p/<peer-id> segment already enforces this at the
transport level (and our invite generator always includes it),
so this is defense in depth — but it makes the assert explicit
rather than relying on a structural side effect.
Sourcepub fn seed_invite_room(&self, room: &InviteRoom)
pub fn seed_invite_room(&self, room: &InviteRoom)
huddle 0.7.12: pre-seed an invite’s room so an immediate join
works without waiting for the host’s gossip announcement to
arrive over the just-opened connection. Decodes the (optional)
salt into ROOM_SALT_CACHE and inserts a discovered_rooms
entry, so join_room can resolve the room’s metadata AND derive
the passphrase key the moment the user submits.
Pre-0.7.12 the invite’s salt_b64 + room metadata were decoded
and then thrown away; join_room could only learn the room from
a live announcement, so submitting the passphrase before that
announcement landed errored “room {id} not found”. The invite
already carries everything required — we just plumb it through.
pub fn known_peers(&self) -> Vec<KnownPeerStatus>
pub async fn forget_peer(&self, address: &str) -> Result<()>
Sourcepub async fn redial(&self, address: &str) -> Result<()>
pub async fn redial(&self, address: &str) -> Result<()>
Re-dial a stored address — used by the lobby’s “reconnect” action.
Sourcepub async fn accept_inbound(&self, peer_id: PeerId, address: &str)
pub async fn accept_inbound(&self, peer_id: PeerId, address: &str)
Phase A: user pressed Accept on the inbound-dial modal. Promotes
the peer to the gossipsub mesh. Does NOT mark them trusted —
that’s trust_inbound, the explicit “remember and bypass next
time” path.
Sourcepub async fn reject_inbound(
&self,
peer_id: PeerId,
fingerprint: &str,
) -> Result<()>
pub async fn reject_inbound( &self, peer_id: PeerId, fingerprint: &str, ) -> Result<()>
Phase A: user pressed Reject on the inbound-dial modal. Disconnects the peer, adds them to the persistent blocklist, and ensures every subsequent connection attempt from this fingerprint is auto- dropped without re-prompting.
Sourcepub async fn trust_inbound(
&self,
peer_id: PeerId,
fingerprint: &str,
address: &str,
) -> Result<()>
pub async fn trust_inbound( &self, peer_id: PeerId, fingerprint: &str, address: &str, ) -> Result<()>
Phase A: user pressed Trust+Accept — accept the connection AND remember the peer so subsequent connections bypass the modal.
Sourcepub fn list_pending_friend_requests(&self) -> Vec<PendingFriendRequest>
pub fn list_pending_friend_requests(&self) -> Vec<PendingFriendRequest>
Snapshot of every inbound dial we’ve spilled to disk but haven’t yet accepted or rejected. The People pane renders this as its own section (“Pending requests (N)”).
Sourcepub fn spill_pending_friend_request(
&self,
peer_id: PeerId,
fingerprint: &str,
address: &str,
) -> Result<()>
pub fn spill_pending_friend_request( &self, peer_id: PeerId, fingerprint: &str, address: &str, ) -> Result<()>
Persist an inbound request that the user didn’t act on within the modal window. Called from the TUI’s idle-timeout sweep; the live libp2p connection is also closed by the same path (the request is effectively rejected for now — accept later from People pane will re-dial the stored address).
Sourcepub async fn accept_pending_friend_request(
&self,
fingerprint: &str,
) -> Result<()>
pub async fn accept_pending_friend_request( &self, fingerprint: &str, ) -> Result<()>
User pressed Accept on a row in the Pending requests list. The original libp2p connection is long gone (we closed it on timeout); re-dial the stored address and mark the peer trusted so the post-Identify handler short-circuits the modal. The row is removed regardless of dial success — a failed dial is still a positive intent we don’t want to keep re-prompting on.
Sourcepub fn reject_pending_friend_request(&self, fingerprint: &str) -> Result<()>
pub fn reject_pending_friend_request(&self, fingerprint: &str) -> Result<()>
User pressed Reject on a row in the Pending requests list.
Mirrors reject_inbound semantics: delete the pending row(s)
AND block the fingerprint so any future dial from this peer is
auto-dropped without re-prompting.
Sourcepub async fn disconnect_peer(&self, peer_id: PeerId)
pub async fn disconnect_peer(&self, peer_id: PeerId)
huddle 0.7.7: close a live libp2p connection without blocking the
peer. Used by the TUI’s 15s InboundDial timeout — we need to
drop the dangling socket, but blocking the peer would
contradict “save the request for 3 days, let the user decide
later.” reject_inbound is the right call when the user
explicitly clicks Reject.
Sourcepub async fn send_file(&self, room_id: &str, path: &Path) -> Result<String>
pub async fn send_file(&self, room_id: &str, path: &Path) -> Result<String>
Send a local file to a room. Reads the file, optionally encrypts it for encrypted rooms, chunks it, broadcasts a FileOffer then each FileChunk. Returns the file_id once all chunks are queued.
Sourcepub async fn save_to_downloads(
&self,
room_id: &str,
file_id: &str,
) -> Result<PathBuf>
pub async fn save_to_downloads( &self, room_id: &str, file_id: &str, ) -> Result<PathBuf>
Save a completed/ready attachment to the user’s Downloads folder. Decrypts encrypted attachments on the way out.
Sourcepub async fn cancel_transfer(&self, room_id: &str, file_id: &str) -> Result<()>
pub async fn cancel_transfer(&self, room_id: &str, file_id: &str) -> Result<()>
Drop any in-flight chunks and remove the attachment row.
Sourcepub fn open_saved(&self, room_id: &str, file_id: &str) -> Result<()>
pub fn open_saved(&self, room_id: &str, file_id: &str) -> Result<()>
Launch the system’s default opener on a saved file.
pub fn list_room_attachments( &self, room_id: &str, ) -> Result<Vec<StoredAttachment>>
Sourcepub fn set_member_verified(
&self,
room_id: &str,
fingerprint: &str,
verified: bool,
) -> Result<()>
pub fn set_member_verified( &self, room_id: &str, fingerprint: &str, verified: bool, ) -> Result<()>
Mark a peer’s fingerprint as verified in the given room. Used by
the ^V verification modal after the user has compared the
fingerprint out-of-band.
pub fn verified_fingerprints(&self, room_id: &str) -> Vec<String>
Sourcepub fn is_owner(&self, room_id: &str, fingerprint: &str) -> bool
pub fn is_owner(&self, room_id: &str, fingerprint: &str) -> bool
Phase B: is fingerprint an owner of room_id? Used by the TUI
to gate ^K / ^G and the kick/grant member-picker actions.
pub fn we_are_owner(&self, room_id: &str) -> bool
Sourcepub fn room_owners(&self, room_id: &str) -> Vec<String>
pub fn room_owners(&self, room_id: &str) -> Vec<String>
Phase B: list current owner fingerprints for room_id — used to
render an owner badge in the member panel.
Sourcepub fn has_master_passphrase(&self) -> bool
pub fn has_master_passphrase(&self) -> bool
huddle 0.7.6: true iff this session was started with a master
passphrase. The TUI uses this to pick the Go Dark gate — passphrase
if available (the natural strong secret the user already knows),
else the typed DELETE EVERYTHING phrase since no-master-passphrase
sessions have nothing else to compare against.
Sourcepub fn verified_only_inbound(&self) -> bool
pub fn verified_only_inbound(&self) -> bool
Phase E: global toggle — when true, inbound dials from unverified fingerprints are auto-rejected without prompting.
pub fn set_verified_only_inbound(&self, on: bool) -> Result<()>
Sourcepub fn mdns_enabled(&self) -> bool
pub fn mdns_enabled(&self) -> bool
huddle 0.7.8: persisted LAN-discovery toggle. When true, the
next launch starts in NetworkMode::Mdns so the device joins
LAN mDNS announcements. When false, the next launch starts in
NetworkMode::Direct — invisible to LAN broadcast; only direct
dial / invite link / configured relays can establish a peer.
Default ON so existing users see no behavior change. Restart
required to apply (libp2p’s Toggle<Mdns> flip would require a
behaviour rebuild; not worth the complexity for a rarely-touched
setting).
pub fn set_mdns_enabled(&self, on: bool) -> Result<()>
Sourcepub fn notifications_enabled(&self) -> bool
pub fn notifications_enabled(&self) -> bool
huddle 0.7.8: persisted desktop-notification opt-out. The
notifier itself is a local-only osascript/notify-send
process call — toggling this OFF skips the call entirely so
nothing reaches the OS notification daemon. Default ON to
preserve current behavior.
pub fn set_notifications_enabled(&self, on: bool) -> Result<()>
Sourcepub fn safety_code(&self) -> String
pub fn safety_code(&self) -> String
huddle 0.7.8: stable 12-hex Safety Code derived from our Ed25519 pubkey. Display-only; used as a quick visual fingerprint match in Profile / Account. SAS-via-emoji remains the actual verification primitive.
Sourcepub fn room_verified_only(&self, room_id: &str) -> bool
pub fn room_verified_only(&self, room_id: &str) -> bool
Phase E: per-room verified-only-join. When true, the host (and
every honest existing member) drops MemberAnnounce from joiners
who aren’t globally SAS-verified, and the lowest-fp owner sends
back a signed JoinRefused so the joiner sees an explanation.
pub fn set_room_verified_only(&self, room_id: &str, on: bool) -> Result<()>
Sourcepub fn onboarding_seen(&self) -> bool
pub fn onboarding_seen(&self) -> bool
Phase H: first-launch onboarding flag.
pub fn mark_onboarding_seen(&self) -> Result<()>
Sourcepub fn last_seen_onboarding_version(&self) -> Option<String>
pub fn last_seen_onboarding_version(&self) -> Option<String>
huddle 0.6: version string of huddle the user last finished
onboarding for. Compared against env!("CARGO_PKG_VERSION") at
startup so a version bump re-fires the “what’s new” card.
pub fn set_last_seen_onboarding_version(&self, version: &str) -> Result<()>
Sourcepub fn update_check_enabled(&self) -> Option<bool>
pub fn update_check_enabled(&self) -> Option<bool>
huddle 0.6: opt-in flag for the crates.io update check.
None ⇒ the user hasn’t been asked yet.
pub fn set_update_check_enabled(&self, enabled: bool) -> Result<()>
Sourcepub fn last_update_check_at(&self) -> i64
pub fn last_update_check_at(&self) -> i64
huddle 0.6: cache anchor for the once-per-24h crates.io poll. Returns 0 if nothing has been recorded yet.
pub fn set_last_update_check_at(&self, ts: i64) -> Result<()>
Sourcepub fn last_known_remote_version(&self) -> Option<String>
pub fn last_known_remote_version(&self) -> Option<String>
huddle 0.6: the most recent max_stable_version we saw on
crates.io. Persisted so a re-launch within the 24h window
can render the banner without re-fetching.
pub fn set_last_known_remote_version(&self, v: &str) -> Result<()>
Sourcepub async fn grant_owner(
&self,
room_id: &str,
target_fingerprint: &str,
) -> Result<()>
pub async fn grant_owner( &self, room_id: &str, target_fingerprint: &str, ) -> Result<()>
Phase B: promote target_fingerprint to owner. Builds a signed
OwnerGrant, broadcasts it, and applies it locally. Returns an
error if we ourselves aren’t an owner — only owners can grant.
Sourcepub async fn kick_member(
&self,
room_id: &str,
target_fingerprint: &str,
) -> Result<String>
pub async fn kick_member( &self, room_id: &str, target_fingerprint: &str, ) -> Result<String>
Phase B: kick target_fingerprint from room_id. Broadcasts a
signed BanMember, records the ban locally, then immediately
rotates the room key under a freshly-generated passphrase. Returns
the new passphrase so the caller can show it to the owner for
out-of-band sharing with remaining members.
The rotation is the cryptographic enforcement: a banned peer can still subscribe to the gossipsub topic and see the ciphertext, but they can’t unwrap the new session key without the new passphrase, so they can’t decrypt anything sent after the kick.
Sourcepub fn generate_join_code(&self, room_id: &str) -> Result<String>
pub fn generate_join_code(&self, room_id: &str) -> Result<String>
Phase F: generate an 8-char alphanumeric join code for room_id,
good for 10 minutes. Stored in memory only on the issuing owner’s
machine — a single use clears it. Caller is responsible for
sharing the code OOB with the prospective joiner.
Owner-only. Errors if room_id isn’t active or we’re not an owner.
Sourcepub async fn join_room_with_code(&self, room_id: &str, code: &str) -> Result<()>
pub async fn join_room_with_code(&self, room_id: &str, code: &str) -> Result<()>
Phase F: join room_id using a short-lived code instead of the
passphrase. Generates an ephemeral X25519 keypair, broadcasts a
signed CodeJoinRequest, and waits for the owner’s
CodeJoinResponse. The receive arm builds an ActiveRoom
flagged read-only (no passphrase = can’t share our outbound
session key with others).
Sourcepub async fn sas_start(
&self,
room_id: &str,
target_fingerprint: &str,
) -> Result<String>
pub async fn sas_start( &self, room_id: &str, target_fingerprint: &str, ) -> Result<String>
Phase G: start an SAS verification with target_fingerprint in
room_id. Returns the tx_id so the caller can correlate
subsequent events. The full flow is asynchronous — the partner
must accept on their end, both compute the ECDH-derived SAS
code, OOB-compare it, and each press Match.
Sourcepub async fn sas_match(&self, tx_id: &str) -> Result<()>
pub async fn sas_match(&self, tx_id: &str) -> Result<()>
Phase G: user pressed Match on the SAS code modal — broadcast our
signed SasConfirm{matched: true}. If the partner has already
matched, this completes verification on both sides.
Sourcepub fn sas_cancel(&self, tx_id: &str)
pub fn sas_cancel(&self, tx_id: &str)
Phase G: cancel an in-flight SAS — drop our local state. Doesn’t broadcast a “matched=false” notice in v1 (partner’s flow stays dangling; they can cancel their side too). Quiet teardown.
pub fn display_name(&self) -> Option<String>
pub fn set_display_name(&self, name: Option<&str>) -> Result<()>
Sourcepub async fn set_username(&self, name: Option<&str>) -> Result<()>
pub async fn set_username(&self, name: Option<&str>) -> Result<()>
huddle 0.5: set the local user’s self-declared username (or clear
it with None) and broadcast a signed ProfileUpdate to every
joined room. Receivers cache the latest per-fingerprint username
in peer_profiles; unsigned envelopes are dropped at the receive
arm so the username can’t be spoofed.
Sourcepub fn lookup_username(&self, fingerprint: &str) -> Option<String>
pub fn lookup_username(&self, fingerprint: &str) -> Option<String>
huddle 0.5: cached username for a peer (any peer we’ve ever
received a signed ProfileUpdate from), or None if unknown or
the peer cleared their username. Callers render [anonymous] on
None.
Sourcepub fn lookup_member_display_name(&self, fingerprint: &str) -> Option<String>
pub fn lookup_member_display_name(&self, fingerprint: &str) -> Option<String>
Look up the display name we’ve seen for a peer. Forwards to
lookup_username (the new signed-source-of-truth) so existing
call sites get the authenticated value without churn.
Sourcepub fn peers_with_username(&self, username: &str) -> Vec<String>
pub fn peers_with_username(&self, username: &str) -> Vec<String>
huddle 0.7.12: reverse of lookup_username — every fingerprint
that has broadcast username via a signed ProfileUpdate.
Usernames aren’t unique, so callers must handle 0 / 1 / many.
Backs the Compose-DM resolver so typing a contact’s name opens a
DM over the existing mesh instead of falling through to a fresh
dial (matching the resolution dial_by_id_or_username already
does for the add-friend flow).
pub fn is_room_muted(&self, room_id: &str) -> bool
Sourcepub fn list_room_bans(&self, room_id: &str) -> Vec<String>
pub fn list_room_bans(&self, room_id: &str) -> Vec<String>
Phase B: list the fingerprints currently banned from a room
(newest first). Backs the ^B in-room view; intended for
owners but the read itself is harmless and we let callers
gate via we_are_owner if they want owner-only display.
Sourcepub fn list_verified_peers(&self) -> Vec<String>
pub fn list_verified_peers(&self) -> Vec<String>
Phase A: list every globally-blocked peer (one fingerprint per
row). Surfaced in the Settings modal alongside a clear-all
action that calls unblock_peer in a loop.
huddle 0.7: every globally SAS-verified peer. Surfaced in the
People pane’s “Verified” sub-list.
pub fn list_blocked_peers(&self) -> Vec<String>
Sourcepub fn unblock_peer(&self, fingerprint: &str) -> Result<()>
pub fn unblock_peer(&self, fingerprint: &str) -> Result<()>
Phase A: remove fingerprint from the persistent blocklist. The
peer will no longer be auto-rejected on connection; they fall
back to the regular inbound-dial accept/reject prompt.
Sourcepub fn block_peer(&self, fingerprint: &str) -> Result<()>
pub fn block_peer(&self, fingerprint: &str) -> Result<()>
huddle 0.7: add fingerprint to the persistent blocklist. Used
by the People pane’s per-row “block” action. Subsequent inbound
dials from this fingerprint are auto-rejected without prompting.
Sourcepub fn is_room_read_only(&self, room_id: &str) -> bool
pub fn is_room_read_only(&self, room_id: &str) -> bool
Phase F: rooms entered via a join code don’t have the passphrase
in memory, so the joining peer can’t wrap their own outbound
session key for newer members — they can read and send, they
just can’t onboard others. The TUI renders a (read-only)
badge in the room tab so the user understands.
pub fn set_room_muted(&self, room_id: &str, muted: bool) -> Result<()>
Sourcepub async fn broadcast_typing(&self, room_id: &str)
pub async fn broadcast_typing(&self, room_id: &str)
Broadcast a “I’m typing” pulse to the given room. Caller is responsible for debouncing (don’t fire more than every ~500ms).
Sourcepub fn typers_in_room(&self, room_id: &str) -> Vec<String>
pub fn typers_in_room(&self, room_id: &str) -> Vec<String>
Returns the fingerprints of peers currently typing in room_id,
pruning entries past their TTL.
Sourcepub async fn rotate_room(
&self,
room_id: &str,
new_passphrase: &str,
) -> Result<()>
pub async fn rotate_room( &self, room_id: &str, new_passphrase: &str, ) -> Result<()>
Rotate this room’s outbound Megolm session under a fresh
passphrase. Broadcasts RotateRoomKey (so other members know to
expect a new passphrase) and a fresh MemberAnnounce with the
new wrapped session key. Old inbound sessions stay in storage
for decrypting historic messages.
Sourcepub async fn accept_rotation(
&self,
room_id: &str,
new_salt: &[u8],
new_passphrase: &str,
) -> Result<()>
pub async fn accept_rotation( &self, room_id: &str, new_salt: &[u8], new_passphrase: &str, ) -> Result<()>
Used by the TUI when another member rotates a room we’re in. Derives the new key, updates our local state, and re-announces so the rotator can share their fresh outbound session with us.
Sourcepub async fn go_dark(&self, master_passphrase: &str) -> Result<()>
pub async fn go_dark(&self, master_passphrase: &str) -> Result<()>
huddle 0.5: irreversibly delete this account. Verifies the
master passphrase, best-effort MemberLeaves every joined room
(capped at 2 s so a single unresponsive transport can’t hang
the wipe), shuts down the network, then deletes the database,
keychain salt, log, and config files from config::data_dir().
Emits AppEvent::WentDark on success so the TUI can show a
goodbye modal and exit.
In --no-master-passphrase mode (self.session_persist_key
is all-zero), the passphrase check is skipped — the typed
DELETE EVERYTHING confirmation in the TUI is the only gate.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for AppHandle
impl !RefUnwindSafe for AppHandle
impl Send for AppHandle
impl Sync for AppHandle
impl Unpin for AppHandle
impl UnsafeUnpin for AppHandle
impl !UnwindSafe for AppHandle
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more