feat: Tambah Ctrl+Y untuk menyalin pesan assistant terakhir
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3b6abd920e
commit
d93bdba59b
@@ -132,6 +132,23 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
||||
KeyCode::Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::CloseOverlay]
|
||||
}
|
||||
KeyCode::Char('y') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
let last_assistant = state.transcript_cache.messages.iter()
|
||||
.rev()
|
||||
.find(|m| m.role == crate::dto::chat::message::Role::Assistant);
|
||||
match last_assistant {
|
||||
Some(msg) => {
|
||||
state.misc.pending_clipboard_copy = Some(msg.content.clone());
|
||||
}
|
||||
None => {
|
||||
state.push_toast(crate::app::state::types::Toast::new(
|
||||
crate::app::state::types::ToastKind::Info,
|
||||
"No assistant message to copy yet".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
if state.input.autocomplete_visible {
|
||||
state.input.select_autocomplete();
|
||||
@@ -371,3 +388,45 @@ fn handle_overlay_enter(state: &mut AppStateRest) -> Vec<Action> {
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn test_state() -> AppStateRest {
|
||||
let tmp = std::env::temp_dir().join(format!("zesdex-input-test-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&tmp).unwrap();
|
||||
AppStateRest::new(vec![tmp.clone()], &tmp, tmp.join("memory"))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ctrl_y_sets_pending_clipboard_copy_to_last_assistant_message() {
|
||||
let mut state = test_state();
|
||||
state.push_transcript(crate::app::state::rest::ChatMessageDisplay::new(
|
||||
crate::dto::chat::message::Role::User,
|
||||
"hi".to_string(),
|
||||
));
|
||||
state.push_transcript(crate::app::state::rest::ChatMessageDisplay::new(
|
||||
crate::dto::chat::message::Role::Assistant,
|
||||
"first reply".to_string(),
|
||||
));
|
||||
state.push_transcript(crate::app::state::rest::ChatMessageDisplay::new(
|
||||
crate::dto::chat::message::Role::Tool,
|
||||
"tool output".to_string(),
|
||||
));
|
||||
state.push_transcript(crate::app::state::rest::ChatMessageDisplay::new(
|
||||
crate::dto::chat::message::Role::Assistant,
|
||||
"second reply".to_string(),
|
||||
));
|
||||
handle_key(KeyEvent::new(KeyCode::Char('y'), KeyModifiers::CONTROL), &mut state);
|
||||
assert_eq!(state.misc.pending_clipboard_copy, Some("second reply".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ctrl_y_with_no_assistant_message_pushes_info_toast() {
|
||||
let mut state = test_state();
|
||||
handle_key(KeyEvent::new(KeyCode::Char('y'), KeyModifiers::CONTROL), &mut state);
|
||||
assert!(state.misc.pending_clipboard_copy.is_none());
|
||||
assert_eq!(state.misc.toasts.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user