feat(identity): copy-to-clipboard button for the node ID (W7)

The Identity section showed only a truncated id and iced text isn't
selectable, so there was no way to share your full node id. Add a Copy
button (mirrors the room-ticket copy) that writes the FULL id to the
clipboard via a new generic CopyText(String) message. Also unblocks the
add-a-friend self-test (copy your id, paste into Add friend).

256 lib tests green, clippy clean, release builds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 04:58:57 -04:00
co-authored by Claude Opus 4.8
parent f161534a4b
commit e3f9cd5be7
+28 -1
View File
@@ -117,6 +117,8 @@ pub enum AppMessage {
ToggleDeafenPressed,
UiEventReceived(UiEvent),
CopyToClipboard,
/// Copy an arbitrary string to the clipboard (e.g. the full node ID).
CopyText(String),
TogglePtt(bool),
StartSettingHotkey,
PeerVolumeChanged(EndpointId, f32),
@@ -691,6 +693,9 @@ fn update(state: &mut AppState, message: AppMessage) -> Task<AppMessage> {
return iced::clipboard::write(state.ticket.clone());
}
}
AppMessage::CopyText(s) => {
return iced::clipboard::write(s);
}
AppMessage::TogglePtt(enabled) => {
state.ptt_enabled = enabled;
let _ = state.controller.send(CoreCommand::SetPttMode(enabled));
@@ -1549,13 +1554,35 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
})
.into()
};
// The ID line shows a short form (iced text isn't selectable) plus a Copy
// button that puts the FULL node id on the clipboard, so it's shareable.
let id_row: Element<AppMessage> = match state.self_node_id.clone() {
Some(full) => row![
text(format!("ID: {id_display}")).size(13).color(color_text),
button(
row![
icon(IconKind::Copy, 13.0, color_text),
text("Copy").size(12),
]
.spacing(5)
.align_y(iced::alignment::Vertical::Center)
)
.on_press(AppMessage::CopyText(full))
.style(b_style(color_surface, color_blue, color_text, 6.0))
.padding(6),
]
.spacing(10)
.align_y(iced::alignment::Vertical::Center)
.into(),
None => text(format!("ID: {id_display}")).size(13).color(color_text).into(),
};
let identity_section = column![
text("Your permanent ID — friends recognise you by this. It stays the \
same across launches; regenerate only to start fresh as a new \
identity (friends who saved the old one will no longer reach you).")
.size(12)
.color(color_subtext),
text(format!("ID: {id_display}")).size(13).color(color_text),
id_row,
button(text("Regenerate identity").size(13))
.on_press(AppMessage::OpenRegenerateIdentityConfirm)
.style(b_style(color_surface, color_maroon, color_text, 6.0))