T23c: AI chat, input
- PromptInput: attachments and context above the field, the owner's tools and send below; Enter sends, Shift-Enter breaks the line; / offers commands and @ offers context over forms::Suggestions; files dropped on it attach behind a drop veil - AttachmentButton, AttachmentChip with thumbnails and uploads, ContextChips - VoiceInputButton and VoiceWaveform with a red dot and the time - ParameterPanel, SystemPromptEditor, TokenCounter, CostEstimator - forms: a Newline action on Shift-Enter keeps one-line fields to one line; replace_trigger moves beside Suggestions; choose and dropped shared - gallery: composer, pickers and tuning
This commit is contained in:
1 parent
fce38dec00
commit
d362f08d41
17 files changed
+1562
-38
No files matched your search
@@ -32,6 +32,20 @@ pub(crate) fn active_trigger(text: &str, caret: usize, triggers: &[char]) -> Opt
|
||||
(opens && word).then_some((ix, ch))
|
||||
}
|
||||
|
||||
/// Replaces the trigger and its query, `at..caret`, with `text`, as one undo step.
|
||||
pub(crate) fn replace_trigger(
|
||||
field: &Entity<TextInput>,
|
||||
at: usize,
|
||||
caret: usize,
|
||||
text: &str,
|
||||
cx: &mut App,
|
||||
) {
|
||||
field.update(cx, |input, cx| {
|
||||
input.select(at..caret, cx);
|
||||
input.insert(text, cx);
|
||||
});
|
||||
}
|
||||
|
||||
/// The dismissed trigger, while it is still the one being typed.
|
||||
fn dismissal(dismissed: Option<usize>, active: Option<usize>) -> Option<usize> {
|
||||
dismissed.filter(|at| active == Some(*at))
|
||||
|
||||
+3
-1
@@ -63,6 +63,7 @@ pub use date::{
|
||||
WeekPicker, YearPicker,
|
||||
};
|
||||
pub use expression::{ExpressionInput, evaluate, expression_highlights};
|
||||
pub(crate) use files::dropped;
|
||||
pub use files::{DropZone, FileInput};
|
||||
pub(crate) use glyphs::emoji_found;
|
||||
pub use glyphs::{EmojiPicker, IconPicker};
|
||||
@@ -75,7 +76,7 @@ pub use knob::Knob;
|
||||
pub use listbox::ListBox;
|
||||
pub use masked::{COUNTRIES, MaskedInput, PhoneInput};
|
||||
pub use mention::{MentionInput, mention_highlights};
|
||||
pub(crate) use mention::{Suggestions, active_trigger, handles_matching};
|
||||
pub(crate) use mention::{Suggestions, active_trigger, handles_matching, replace_trigger};
|
||||
pub use multi::MultiSelect;
|
||||
pub use number::{NumberInput, ScrubInput};
|
||||
pub use options::Choice;
|
||||
@@ -84,6 +85,7 @@ pub(crate) use options::{
|
||||
};
|
||||
pub use pairs::{FieldArray, KeyValueInput, ListInput};
|
||||
pub use path::PathInput;
|
||||
pub(crate) use path::choose;
|
||||
pub use pattern::{RegexInput, regex_highlights};
|
||||
pub use pin::PinInput;
|
||||
pub use radio::{Radio, RadioGroup};
|
||||
|
||||
@@ -299,3 +299,17 @@ fn a_range_gives_a_box_per_line_it_spans(cx: &mut TestAppContext) {
|
||||
"the second line starts at the edge"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn shift_enter_breaks_only_a_field_of_many_lines(cx: &mut TestAppContext) {
|
||||
let (fields, cx) = open(1, false, cx);
|
||||
focus(&fields[0], cx);
|
||||
cx.simulate_input("one line");
|
||||
cx.simulate_keystrokes("shift-enter");
|
||||
cx.run_until_parked();
|
||||
assert_eq!(
|
||||
text(&fields[0], cx),
|
||||
"one line",
|
||||
"a single line stays single"
|
||||
);
|
||||
}
|
||||
@@ -39,6 +39,7 @@ actions!(
|
||||
Undo,
|
||||
Redo,
|
||||
Enter,
|
||||
Newline,
|
||||
Submit,
|
||||
ShowCharacterPalette,
|
||||
]
|
||||
@@ -84,6 +85,7 @@ pub(crate) fn bind_keys(cx: &mut App) {
|
||||
KeyBinding::new("secondary-z", Undo, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-shift-z", Redo, Some(CONTEXT)),
|
||||
KeyBinding::new("enter", Enter, Some(CONTEXT)),
|
||||
KeyBinding::new("shift-enter", Newline, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-enter", Submit, Some(CONTEXT)),
|
||||
];
|
||||
if cfg!(target_os = "macos") {
|
||||
@@ -290,6 +292,12 @@ impl TextInput {
|
||||
}
|
||||
}
|
||||
|
||||
fn newline(&mut self, _: &Newline, _: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.rows.is_some() {
|
||||
self.replace(self.selection.clone(), "\n", false, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn submit(&mut self, _: &Submit, _: &mut Window, cx: &mut Context<Self>) {
|
||||
log::info!("text input: submitted");
|
||||
cx.emit(InputEvent::Submit);
|
||||
@@ -380,6 +388,7 @@ impl Render for TextInput {
|
||||
.on_action(cx.listener(Self::undo))
|
||||
.on_action(cx.listener(Self::redo))
|
||||
.on_action(cx.listener(Self::enter))
|
||||
.on_action(cx.listener(Self::newline))
|
||||
.on_action(cx.listener(Self::submit))
|
||||
.on_action(cx.listener(Self::show_character_palette))
|
||||
.on_mouse_down(MouseButton::Left, cx.listener(Self::mouse_down))
|
||||
|
||||
Reference in new issue
Block a user