feat(w7): add-friend-from-room — friend a co-participant with one click (P5)
Each participant card gets a star affordance: a clickable outline star (☆) that adds that peer to your friends list, or a non-interactive gold filled star (★) once they're already a friend (hidden while the friends store is read-only). The add pulls the peer's live presence name + address from the room roster and passes addr: Some(..) to CoreCommand::AddFriend, so the new friend is reachable immediately — no waiting for a future call to seed last_addr the way a bare add-by-id does. Name sanitized, short-id fallback; idempotent in core; no-op if already a friend. New AppMessage::AddFriendFromRoom(EndpointId). clippy --all-targets clean, 257 lib tests green. UI wiring screenshot-pending: the star + click need a live 2-machine call (a peer in the room) to verify visually. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -145,6 +145,9 @@ pub enum AppMessage {
|
||||
FriendAddIdChanged(String),
|
||||
FriendAddNameChanged(String),
|
||||
AddFriend,
|
||||
/// Add a peer you're in a call with to your friends list (W7), using their
|
||||
/// live presence name + address so they're reachable immediately.
|
||||
AddFriendFromRoom(EndpointId),
|
||||
RemoveFriend(EndpointId),
|
||||
RenameFriend(EndpointId, String),
|
||||
/// Join the gathering a friend is in (W7 B2), via the member ticket their
|
||||
@@ -837,6 +840,26 @@ fn update(state: &mut AppState, message: AppMessage) -> Task<AppMessage> {
|
||||
}
|
||||
}
|
||||
}
|
||||
AppMessage::AddFriendFromRoom(id) => {
|
||||
// Add a co-participant: pull their name + live address from the room
|
||||
// roster so the friend is reachable right away (no wait for a future
|
||||
// call to seed last_addr, unlike a bare add-by-id). No-op if read-only
|
||||
// or already a friend; idempotent in core regardless.
|
||||
if !state.friends_read_only
|
||||
&& !state.friends.contains(&id)
|
||||
&& let Some(peer) = state.peers.get(&id)
|
||||
{
|
||||
let name = {
|
||||
let n = crate::sanitize::sanitize_name(&peer.name);
|
||||
if n.is_empty() { short_id(&id.to_string()) } else { n }
|
||||
};
|
||||
let _ = state.controller.send(CoreCommand::AddFriend {
|
||||
id,
|
||||
name,
|
||||
addr: Some(peer.addr.clone()),
|
||||
});
|
||||
}
|
||||
}
|
||||
AppMessage::RemoveFriend(id) => {
|
||||
if !state.friends_read_only {
|
||||
let _ = state.controller.send(CoreCommand::RemoveFriend(id));
|
||||
@@ -2405,6 +2428,36 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
|
||||
color_surface
|
||||
};
|
||||
|
||||
// Add-friend affordance (W7): a star you can click to friend this
|
||||
// co-participant; a filled gold star (non-interactive) once they're a
|
||||
// friend. Hidden while their friend state is read-only-degraded.
|
||||
let add_friend_el: Element<'_, AppMessage> = if state.friends_read_only {
|
||||
iced::widget::Space::new().width(0.0).height(0.0).into()
|
||||
} else if state.friends.contains(peer_id) {
|
||||
tooltip(
|
||||
text("★").size(16).color(color_yellow),
|
||||
container(text("In your friends list").size(11).color(color_text))
|
||||
.padding(8)
|
||||
.style(c_style(color_crust, color_surface, 6.0)),
|
||||
iced::widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.gap(6)
|
||||
.into()
|
||||
} else {
|
||||
tooltip(
|
||||
button(text("☆").size(16).color(color_subtext))
|
||||
.on_press(AppMessage::AddFriendFromRoom(peer_id_clone))
|
||||
.style(b_style(color_surface, color_blue, color_text, 6.0))
|
||||
.padding([2, 6]),
|
||||
container(text("Add to your friends list").size(11).color(color_text))
|
||||
.padding(8)
|
||||
.style(c_style(color_crust, color_surface, 6.0)),
|
||||
iced::widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.gap(6)
|
||||
.into()
|
||||
};
|
||||
|
||||
let mut card_content = column![
|
||||
row![
|
||||
avatar_view(&peer.avatar, &peer.name, &peer_id.to_string(), 38.0),
|
||||
@@ -2412,6 +2465,7 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
|
||||
text(&peer.name).size(16).color(color_text),
|
||||
text(format!("ID: {}", short_id(&peer_id.to_string()))).size(11).color(color_subtext)
|
||||
],
|
||||
add_friend_el,
|
||||
horizontal_space(),
|
||||
share_el,
|
||||
mute_btn,
|
||||
|
||||
Reference in New Issue
Block a user