commit e549c4db80e7c6d4512ad9cbd3781459cfede6b6
parent 5e47747c39f7d8cabc4fd2d2047c7393002608dc
Author: William Casarin <jb55@jb55.com>
Date: Wed, 18 Feb 2026 15:50:33 -0800
dave: add copy/paste context menus for messages and input box
Long-press (mobile) or right-click (desktop) on user and assistant
messages shows a Copy option. The input box gets the full
Paste/Copy/Cut context menu via the existing input_context helper.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/crates/notedeck_dave/src/ui/dave.rs b/crates/notedeck_dave/src/ui/dave.rs
@@ -270,7 +270,7 @@ impl<'a> DaveUi<'a> {
.inner_margin(egui::Margin::same(8))
.fill(ui.visuals().extreme_bg_color)
.corner_radius(12.0)
- .show(ui, |ui| self.inputbox(app_ctx.i18n, ui))
+ .show(ui, |ui| self.inputbox(app_ctx, ui))
.inner;
{
@@ -1016,7 +1016,8 @@ impl<'a> DaveUi<'a> {
note_action
}
- fn inputbox(&mut self, i18n: &mut Localization, ui: &mut egui::Ui) -> DaveResponse {
+ fn inputbox(&mut self, app_ctx: &mut AppContext, ui: &mut egui::Ui) -> DaveResponse {
+ let i18n = &mut *app_ctx.i18n;
//ui.add_space(Self::chat_margin(ui.ctx()) as f32);
ui.horizontal(|ui| {
ui.with_layout(Layout::right_to_left(Align::Max), |ui| {
@@ -1073,7 +1074,13 @@ impl<'a> DaveUi<'a> {
)
.frame(false),
);
- notedeck_ui::include_input(ui, &r);
+ notedeck_ui::context_menu::input_context(
+ ui,
+ &r,
+ app_ctx.clipboard,
+ self.input,
+ notedeck_ui::context_menu::PasteBehavior::Append,
+ );
// Request focus if flagged (e.g., after spawning a new agent or entering tentative state)
if *self.focus_requested {
@@ -1102,7 +1109,7 @@ impl<'a> DaveUi<'a> {
fn user_chat(&self, msg: &str, ui: &mut egui::Ui) {
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
- egui::Frame::new()
+ let r = egui::Frame::new()
.inner_margin(10.0)
.corner_radius(10.0)
.fill(ui.visuals().widgets.inactive.weak_bg_fill)
@@ -1112,7 +1119,13 @@ impl<'a> DaveUi<'a> {
.wrap_mode(egui::TextWrapMode::Wrap)
.selectable(true),
);
- })
+ });
+ r.response.context_menu(|ui| {
+ if ui.button("Copy").clicked() {
+ ui.ctx().copy_text(msg.to_owned());
+ ui.close_menu();
+ }
+ });
});
}
@@ -1120,7 +1133,16 @@ impl<'a> DaveUi<'a> {
let elements = msg.parsed_elements();
let partial = msg.partial();
let buffer = msg.buffer();
- markdown_ui::render_assistant_message(elements, partial, buffer, ui);
+ let text = msg.text().to_owned();
+ let r = ui.scope(|ui| {
+ markdown_ui::render_assistant_message(elements, partial, buffer, ui);
+ });
+ r.response.context_menu(|ui| {
+ if ui.button("Copy").clicked() {
+ ui.ctx().copy_text(text.clone());
+ ui.close_menu();
+ }
+ });
}
}