feat(friends): friend store, mutual handshake, and Friends UI (phase 3)
Build the friends feature on top of the phase-2 control plane: you can now befriend someone you've connected with and manage a contacts list. - common/friends.rs: a persisted FriendStore in its own friends.toml (kept out of config.toml so a headless --reconfigure can't clobber it, same as identity.key). Friends are keyed by stable control EndpointId; state is PendingOutgoing / PendingIncoming / Accepted. The handshake transitions (on_friend_request → mutual-match detection, on_friend_ accept) are pure and unit-tested. - gui/code.rs: the bootstrap. The GUI host wraps its share code as `pixelpassF1:<control-id>.<ticket>` so a viewer learns the host's stable id; unwrap is lenient, so a bare/CLI ticket still works (no friend offer). The video/streaming path is untouched. - presence service gains an outbound path (unbounded channel → per-msg send tasks) and exposes our control id for wrapping codes. - gui wiring: on connect, the viewer announces itself to the host with a Hello (carrying our display name); the host replies once, so both ends learn each other and an "Add friend" offer appears on the running host/view screens. Incoming requests/accepts/declines fold into the store with desktop notifications. New Friends screen (accept/decline/ remove, edit your display name, see your id) reachable from the menu, which shows a pending-request count. New [gui] display_name setting, seeded from $USER. Verified: friends store + handshake transitions covered by unit tests (7); code wrap/unwrap round-trips (4); the control loopback still passes; the live GUI starts clean with the presence endpoint online. fmt + clippy clean on both features; 41 gui + 8 headless tests pass. The full two-party UX (connect → mutual add → persisted) wants a cross-machine manual check, as usual. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -82,10 +82,6 @@ fn decode(bytes: &[u8]) -> Result<ControlMsg> {
|
||||
/// `peer` is usually a bare [`EndpointId`] — friends store only the stable id,
|
||||
/// and n0 DNS discovery resolves it to a live address. The full [`EndpointAddr`]
|
||||
/// form exists for callers that already hold one (and for hermetic tests).
|
||||
//
|
||||
// Lands ahead of its caller: the outbound paths (friend requests, code pushes)
|
||||
// are wired into the GUI in Phase 3/4. The loopback test exercises it now.
|
||||
#[allow(dead_code)]
|
||||
pub async fn send(
|
||||
endpoint: &Endpoint,
|
||||
peer: impl Into<EndpointAddr>,
|
||||
|
||||
Reference in New Issue
Block a user