chore: improve message copying functionality (#53)

* chore: improve message copying functionality

* .

* clean up
This commit is contained in:
reya
2025-05-31 07:29:56 +07:00
committed by GitHub
parent 7cc512331b
commit 50beaebd2c
2 changed files with 52 additions and 27 deletions

3
assets/icons/copy.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8.75 8v.75m0-3.75v-.25a2 2 0 0 1 2-2H11m8 0h.25a2 2 0 0 1 2 2V5M14 2.75h2M21.25 8v2m0 3v.25a2 2 0 0 1-2 2H19m-3 0h-.75M14 8.75H4c-.69 0-1.25.56-1.25 1.25v10c0 .69.56 1.25 1.25 1.25h10c.69 0 1.25-.56 1.25-1.25V10c0-.69-.56-1.25-1.25-1.25Z"/>
</svg>

After

Width:  |  Height:  |  Size: 444 B

View File

@@ -10,10 +10,10 @@ use common::{nip96_upload, profile::RenderProfile};
use global::get_client; use global::get_client;
use gpui::{ use gpui::{
div, img, impl_internal_actions, list, prelude::FluentBuilder, px, red, relative, rems, svg, div, img, impl_internal_actions, list, prelude::FluentBuilder, px, red, relative, rems, svg,
white, AnyElement, App, AppContext, Context, Div, Element, Empty, Entity, EventEmitter, white, AnyElement, App, AppContext, ClipboardItem, Context, Div, Element, Empty, Entity,
Flatten, FocusHandle, Focusable, InteractiveElement, IntoElement, ListAlignment, ListState, EventEmitter, Flatten, FocusHandle, Focusable, InteractiveElement, IntoElement, ListAlignment,
ObjectFit, ParentElement, PathPromptOptions, Render, RetainAllImageCache, SharedString, ListState, ObjectFit, ParentElement, PathPromptOptions, Render, RetainAllImageCache,
StatefulInteractiveElement, Styled, StyledImage, Subscription, Window, SharedString, StatefulInteractiveElement, Styled, StyledImage, Subscription, Window,
}; };
use itertools::Itertools; use itertools::Itertools;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
@@ -30,7 +30,7 @@ use ui::{
notification::Notification, notification::Notification,
popup_menu::PopupMenu, popup_menu::PopupMenu,
text::RichText, text::RichText,
v_flex, ContextModal, Disableable, Icon, IconName, Sizable, StyledExt, v_flex, ContextModal, Disableable, Icon, IconName, InteractiveElementExt, Sizable, StyledExt,
}; };
use crate::views::subject; use crate::views::subject;
@@ -700,28 +700,50 @@ impl Chat {
) )
.child(message_border(cx)) .child(message_border(cx))
.child(message_actions( .child(message_actions(
vec![Button::new("reply") vec![
Button::new("reply")
.icon(IconName::Reply) .icon(IconName::Reply)
.tooltip("Reply") .tooltip("Reply")
.small() .small()
.ghost() .ghost()
.on_click({ .on_click({
let message = message.clone(); let message = message.clone();
cx.listener(move |this, _, _, cx| { cx.listener(move |this, _event, _window, cx| {
this.reply(message.clone(), cx); this.reply(message.clone(), cx);
}) })
})], }),
Button::new("copy")
.icon(IconName::Copy)
.tooltip("Copy Message")
.small()
.ghost()
.on_click({
let content = ClipboardItem::new_string(message.content.to_string());
cx.listener(move |_this, _event, _window, cx| {
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
cx.write_to_primary(content.clone());
#[cfg(any(target_os = "windows", target_os = "macos"))]
cx.write_to_clipboard(content.clone());
})
}),
],
cx, cx,
)) ))
.on_mouse_down( .on_mouse_down(gpui::MouseButton::Middle, {
gpui::MouseButton::Middle, let content = ClipboardItem::new_string(message.content.to_string());
cx.listener({ cx.listener(move |_this, _event, _window, cx| {
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
cx.write_to_primary(content.clone());
#[cfg(any(target_os = "windows", target_os = "macos"))]
cx.write_to_clipboard(content.clone());
})
})
.on_double_click(cx.listener({
let message = message.clone(); let message = message.clone();
move |this, _, _window, cx| { move |this, _, _window, cx| {
this.reply(message.clone(), cx); this.reply(message.clone(), cx);
} }
}), }))
)
.hover(|this| this.bg(cx.theme().surface_background)) .hover(|this| this.bg(cx.theme().surface_background))
} }
} }
@@ -885,7 +907,7 @@ fn message_errors(errors: Vec<SendError>, cx: &App) -> Div {
})) }))
} }
fn message_actions(buttons: Vec<Button>, cx: &App) -> Div { fn message_actions(buttons: impl IntoIterator<Item = impl IntoElement>, cx: &App) -> Div {
div() div()
.group_hover("", |this| this.visible()) .group_hover("", |this| this.visible())
.invisible() .invisible()
@@ -899,6 +921,6 @@ fn message_actions(buttons: Vec<Button>, cx: &App) -> Div {
.bg(cx.theme().background) .bg(cx.theme().background)
.p_0p5() .p_0p5()
.flex() .flex()
.gap_0p5() .gap_1()
.children(buttons) .children(buttons)
} }