input: Fix crash cause by incorrect selected range. (#560)
The `selected_range` should be UTF-8.
This commit is contained in:
parent
493acdefab
commit
73c92f3a6b
1 changed files with 25 additions and 9 deletions
|
|
@ -169,6 +169,10 @@ pub struct TextInput {
|
|||
pub(super) suffix: Option<Box<dyn Fn(&mut ViewContext<Self>) -> AnyElement + 'static>>,
|
||||
pub(super) loading: bool,
|
||||
pub(super) placeholder: SharedString,
|
||||
/// Range in UTF-8 length for the selected text.
|
||||
///
|
||||
/// - "Hello 世界💝" = 16
|
||||
/// - "💝" = 4
|
||||
pub(super) selected_range: Range<usize>,
|
||||
/// Range for save the selected word, use to keep word range when drag move.
|
||||
pub(super) selected_word_range: Option<Range<usize>>,
|
||||
|
|
@ -609,7 +613,7 @@ impl TextInput {
|
|||
return;
|
||||
}
|
||||
let offset = (self.end_of_line(cx) + 1).min(self.text.len());
|
||||
self.select_to(offset, cx);
|
||||
self.select_to(self.next_boundary(offset), cx);
|
||||
}
|
||||
|
||||
fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
|
||||
|
|
@ -649,12 +653,12 @@ impl TextInput {
|
|||
|
||||
fn select_to_start_of_line(&mut self, _: &SelectToStartOfLine, cx: &mut ViewContext<Self>) {
|
||||
let offset = self.start_of_line(cx);
|
||||
self.select_to(offset, cx);
|
||||
self.select_to(self.previous_boundary(offset), cx);
|
||||
}
|
||||
|
||||
fn select_to_end_of_line(&mut self, _: &SelectToEndOfLine, cx: &mut ViewContext<Self>) {
|
||||
let offset = self.end_of_line(cx);
|
||||
self.select_to(offset, cx);
|
||||
self.select_to(self.next_boundary(offset), cx);
|
||||
}
|
||||
|
||||
/// Get start of line
|
||||
|
|
@ -772,9 +776,9 @@ impl TextInput {
|
|||
}
|
||||
|
||||
if event.modifiers.shift {
|
||||
self.select_to(offset, cx);
|
||||
self.select_to(self.next_boundary(offset), cx);
|
||||
} else {
|
||||
self.move_to(offset, cx)
|
||||
self.move_to(self.next_boundary(offset), cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -815,8 +819,7 @@ impl TextInput {
|
|||
return;
|
||||
}
|
||||
|
||||
let range = self.range_from_utf16(&self.selected_range);
|
||||
let selected_text = self.text[range].to_string();
|
||||
let selected_text = self.text[self.selected_range.clone()].to_string();
|
||||
cx.write_to_clipboard(ClipboardItem::new_string(selected_text));
|
||||
self.replace_text_in_range(None, "", cx);
|
||||
}
|
||||
|
|
@ -873,6 +876,11 @@ impl TextInput {
|
|||
self.history.ignore = false;
|
||||
}
|
||||
|
||||
/// Move the cursor to the given offset.
|
||||
///
|
||||
/// The offset is the UTF-8 offset.
|
||||
///
|
||||
/// Ensure the offset use self.next_boundary or self.previous_boundary to get the correct offset.
|
||||
fn move_to(&mut self, offset: usize, cx: &mut ViewContext<Self>) {
|
||||
self.selected_range = offset..offset;
|
||||
self.pause_blink_cursor(cx);
|
||||
|
|
@ -980,6 +988,11 @@ impl TextInput {
|
|||
}
|
||||
}
|
||||
|
||||
/// Select the text from the current cursor position to the given offset.
|
||||
///
|
||||
/// The offset is the UTF-8 offset.
|
||||
///
|
||||
/// Ensure the offset use self.next_boundary or self.previous_boundary to get the correct offset.
|
||||
fn select_to(&mut self, offset: usize, cx: &mut ViewContext<Self>) {
|
||||
if self.selection_reversed {
|
||||
self.selected_range.start = offset
|
||||
|
|
@ -1008,6 +1021,8 @@ impl TextInput {
|
|||
}
|
||||
|
||||
/// Select the word at the given offset.
|
||||
///
|
||||
/// The offset is the UTF-8 offset.
|
||||
fn select_word(&mut self, offset: usize, cx: &mut ViewContext<Self>) {
|
||||
fn is_word(c: char) -> bool {
|
||||
c.is_alphanumeric() || matches!(c, '_')
|
||||
|
|
@ -1047,7 +1062,8 @@ impl TextInput {
|
|||
}
|
||||
|
||||
fn unselect(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.selected_range = self.cursor_offset()..self.cursor_offset();
|
||||
let offset = self.next_boundary(self.cursor_offset());
|
||||
self.selected_range = offset..offset;
|
||||
cx.notify()
|
||||
}
|
||||
|
||||
|
|
@ -1152,7 +1168,7 @@ impl TextInput {
|
|||
}
|
||||
|
||||
let offset = self.index_for_mouse_position(event.position, cx);
|
||||
self.select_to(offset, cx);
|
||||
self.select_to(self.next_boundary(offset), cx);
|
||||
}
|
||||
|
||||
fn is_valid_input(&self, new_text: &str) -> bool {
|
||||
|
|
|
|||
Loading…
Reference in a new issue