-
Notifications
You must be signed in to change notification settings - Fork 24
Add mention insertion methods #698
Changes from 110 commits
5ebaa7a
be47ece
e10c98c
3a42bc9
6ac6e91
d1fe1e5
2134820
c83efeb
e7ab088
b44b8e5
15e65f5
8d75502
351eaa3
603f9bb
cf8439e
e3eae17
9338af3
4b01334
c70a71b
58a41a1
017bfc1
cce8148
5af177f
d1b11c3
e346446
646decc
c3e29b7
47726ce
923106f
c61787e
f743ab5
7beeeb8
0d25965
2a71a63
86a493c
431b560
ed48f07
421779c
d690b22
5daf120
0cbeedf
15fd087
d0cc42f
6d5d594
88d1c94
f1d4d1e
4519656
83fce36
78e8fbf
338f925
d4ef5c7
e81b109
a8e924a
284b933
269ee3c
37e07f4
0a4aff8
76d0ba4
3387042
8fe0b17
c8b9a55
3b1a618
dc8c863
ae4a3ad
9c93930
b8d7180
1c01f58
7ab6e72
c16d589
ebfb120
9f7ddb5
445d935
86b0688
e11dde8
974759f
c4e331b
66c2e9f
0cdb926
7ad28e5
b239201
99bb780
537d58f
53debd4
8e15970
085f1ef
e0e0177
044dea6
12f5c9f
6755468
cac737f
40329d3
2b6cf0b
a3349d0
95ca657
706000c
81cbb11
0bd1927
416af99
d052012
9a5153b
db197d5
ce4ca7c
3187e78
031b979
a4cafa0
ed92b73
cb0cd27
441b39d
ec46935
49b40e7
b9588fb
65fbaf5
924b36a
31a7bcf
3f6e1ba
55ca905
2cb265c
9bd5a9c
cd8b839
a3cadae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright 2023 The Matrix.org Foundation C.I.C. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use crate::{ | ||
dom::DomLocation, ComposerModel, ComposerUpdate, DomNode, Location, | ||
SuggestionPattern, UnicodeString, | ||
}; | ||
|
||
impl<S> ComposerModel<S> | ||
where | ||
S: UnicodeString, | ||
{ | ||
/// Remove the suggestion text and then add a mention to the composer | ||
pub fn insert_mention_at_suggestion( | ||
&mut self, | ||
url: S, | ||
text: S, | ||
suggestion: SuggestionPattern, | ||
attributes: Vec<(S, S)>, | ||
) -> ComposerUpdate<S> { | ||
// This function removes the text between the suggestion start and end points, updates the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We must |
||
// cursor position and then calls insert_mention (equivalent to link insertion steps) | ||
self.do_replace_text_in(S::default(), suggestion.start, suggestion.end); | ||
self.state.start = Location::from(suggestion.start); | ||
self.state.end = self.state.start; | ||
|
||
self.insert_mention(url, text, attributes) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should really rather call the internal |
||
} | ||
|
||
/// Inserts a mention into the composer. It uses the following rules: | ||
/// - If the selection or cursor contains/is inside a link, do nothing (see | ||
/// https://github.com/matrix-org/matrix-rich-text-editor/issues/702) | ||
/// - If the composer contains a selection, remove the contents of the selection | ||
/// prior to inserting a mention at the cursor. | ||
/// - If the composer contains a cursor, insert a mention at the cursor | ||
pub fn insert_mention( | ||
aringenbach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
&mut self, | ||
url: S, | ||
text: S, | ||
attributes: Vec<(S, S)>, | ||
) -> ComposerUpdate<S> { | ||
let (start, end) = self.safe_selection(); | ||
let range = self.state.dom.find_range(start, end); | ||
|
||
if range.locations.iter().any(|l: &DomLocation| { | ||
l.kind.is_link_kind() || l.kind.is_code_kind() | ||
}) { | ||
return ComposerUpdate::keep(); | ||
} | ||
|
||
aringenbach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if range.is_selection() { | ||
self.replace_text(S::default()); | ||
} | ||
|
||
self.do_insert_mention(url, text, attributes) | ||
} | ||
|
||
fn do_insert_mention( | ||
&mut self, | ||
url: S, | ||
text: S, | ||
attributes: Vec<(S, S)>, | ||
) -> ComposerUpdate<S> { | ||
let (start, end) = self.safe_selection(); | ||
let range = self.state.dom.find_range(start, end); | ||
|
||
let new_node = DomNode::new_mention(url, text, attributes); | ||
let new_cursor_index = start + new_node.text_len(); | ||
|
||
self.push_state_to_history(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably never |
||
|
||
let handle = self.state.dom.insert_node_at_cursor(&range, new_node); | ||
|
||
// manually move the cursor to the end of the mention | ||
self.state.start = Location::from(new_cursor_index); | ||
self.state.end = self.state.start; | ||
|
||
// add a trailing space in cases when we do not have a next sibling | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not completely sure if this is the correct logic or whether we want to simply always add a trailing space for the initial implementation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally I think the behaviour you've implemented makes sense but could be worth checking with UX if you're not sure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah this was already discussed at some point, the conversation lies somewhere in our Room history, but yeah adding a space after the inserted trailing function only is the way to go. |
||
if self.state.dom.is_last_in_parent(&handle) { | ||
self.do_replace_text(" ".into()) | ||
} else { | ||
self.create_update_replace_all() | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,12 @@ where | |
pub(crate) fn compute_menu_action(&self) -> MenuAction { | ||
let (s, e) = self.safe_selection(); | ||
let range = self.state.dom.find_range(s, e); | ||
if range.locations.iter().any(|l| l.kind.is_code_kind()) { | ||
|
||
if range | ||
.locations | ||
.iter() | ||
.any(|l| l.kind.is_code_kind() || l.kind.is_link_kind()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See issue #702, initial implementation is to simply not allow suggestions when inside a link |
||
{ | ||
return MenuAction::None; | ||
} | ||
let (raw_text, start, end) = self.extended_text(range); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update
is unused now