commit d4681801e8fd105331110249fbaa121bd1854da5
parent 9ec5f1efa2715b5792c24c05c26c7c29e27cef5c
Author: William Casarin <jb55@jb55.com>
Date: Mon, 21 Apr 2025 17:10:03 -0700
dave: add new chat button
Diffstat:
2 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/crates/notedeck_dave/src/lib.rs b/crates/notedeck_dave/src/lib.rs
@@ -157,6 +157,11 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
DaveUi::new(&self.chat, &mut self.input).ui(app_ctx, ui)
}
+ fn handle_new_chat(&mut self) {
+ self.chat = vec![];
+ self.input.clear();
+ }
+
/// Handle a user send action triggered by the ui
fn handle_user_send(&mut self, app_ctx: &AppContext, ui: &egui::Ui) {
self.chat.push(Message::User(self.input.clone()));
@@ -296,6 +301,9 @@ impl notedeck::App for Dave {
let should_send = self.process_events(ctx);
if let Some(action) = self.ui(ctx, ui).action {
match action {
+ DaveAction::NewChat => {
+ self.handle_new_chat();
+ }
DaveAction::Send => {
self.handle_user_send(ctx, ui);
}
diff --git a/crates/notedeck_dave/src/ui/dave.rs b/crates/notedeck_dave/src/ui/dave.rs
@@ -21,13 +21,23 @@ pub struct DaveResponse {
}
impl DaveResponse {
- /// Generate a send response to the controller
- fn send() -> Self {
+ fn new(action: DaveAction) -> Self {
+ DaveResponse {
+ action: Some(action),
+ }
+ }
+
+ fn or(self, r: DaveResponse) -> DaveResponse {
DaveResponse {
- action: Some(DaveAction::Send),
+ action: self.action.or(r.action),
}
}
+ /// Generate a send response to the controller
+ fn send() -> Self {
+ Self::new(DaveAction::Send)
+ }
+
fn none() -> Self {
DaveResponse::default()
}
@@ -40,6 +50,7 @@ impl DaveResponse {
pub enum DaveAction {
/// The action generated when the user sends a message to dave
Send,
+ NewChat,
}
impl<'a> DaveUi<'a> {
@@ -67,7 +78,22 @@ impl<'a> DaveUi<'a> {
/// The main render function. Call this to render Dave
pub fn ui(&mut self, app_ctx: &mut AppContext, ui: &mut egui::Ui) -> DaveResponse {
+ let mut action: Option<DaveAction> = None;
// Scroll area for chat messages
+ let new_resp = {
+ let mut rect = ui.available_rect_before_wrap();
+ rect = rect.translate(egui::vec2(20.0, 20.0));
+ rect.set_width(32.0);
+ rect.set_height(32.0);
+ ui.put(rect, new_chat_button())
+ };
+
+ if new_resp.clicked() {
+ action = Some(DaveAction::NewChat);
+ } else if new_resp.hovered() {
+ notedeck_ui::show_pointer(ui);
+ }
+
egui::Frame::NONE
.show(ui, |ui| {
ui.with_layout(Layout::bottom_up(Align::Min), |ui| {
@@ -82,7 +108,6 @@ impl<'a> DaveUi<'a> {
})
.inner_margin(egui::Margin::same(8))
.fill(ui.visuals().extreme_bg_color)
- //.stroke(stroke)
.corner_radius(12.0)
.show(ui, |ui| self.inputbox(ui))
.inner;
@@ -103,6 +128,7 @@ impl<'a> DaveUi<'a> {
.inner
})
.inner
+ .or(DaveResponse { action })
}
/// Render a chat message (user, assistant, tool call/response, etc)
@@ -251,3 +277,29 @@ impl<'a> DaveUi<'a> {
});
}
}
+
+fn new_chat_button() -> impl egui::Widget {
+ move |ui: &mut egui::Ui| {
+ let img_size = 24.0;
+ let max_size = 32.0;
+
+ let img_data = egui::include_image!("../../../../assets/icons/newmessage_64.png");
+ let img = egui::Image::new(img_data).max_width(img_size);
+
+ let helper = notedeck_ui::anim::AnimationHelper::new(
+ ui,
+ "new-chat-button",
+ egui::vec2(max_size, max_size),
+ );
+
+ let cur_img_size = helper.scale_1d_pos(img_size);
+ img.paint_at(
+ ui,
+ helper
+ .get_animation_rect()
+ .shrink((max_size - cur_img_size) / 2.0),
+ );
+
+ helper.take_animation_response()
+ }
+}