Skip to content
This repository has been archived by the owner on Sep 27, 2024. It is now read-only.

Commit

Permalink
get_mentions_state() implemented on the Rust side (only for users and
Browse files Browse the repository at this point in the history
@room) (#849)

* get_mentions_state() implemented and tested

* more tests

* more tests

* Update crates/wysiwyg/src/mentions_state.rs

Co-authored-by: jonnyandrew <[email protected]>

* added also parsing for the rooms

---------

Co-authored-by: jonnyandrew <[email protected]>
  • Loading branch information
Velin92 and jonnyandrew authored Oct 19, 2023
1 parent 0663938 commit 9d60d40
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 27 deletions.
5 changes: 5 additions & 0 deletions bindings/wysiwyg-ffi/src/ffi_composer_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::ffi_composer_state::ComposerState;
use crate::ffi_composer_update::ComposerUpdate;
use crate::ffi_dom_creation_error::DomCreationError;
use crate::ffi_link_actions::LinkAction;
use crate::ffi_mentions_state::MentionsState;
use crate::into_ffi::IntoFfi;
use crate::{ActionState, ComposerAction, SuggestionPattern};

Expand Down Expand Up @@ -370,6 +371,10 @@ impl ComposerModel {
self.inner.lock().unwrap().get_link_action().into()
}

pub fn get_mentions_state(self: &Arc<Self>) -> MentionsState {
self.inner.lock().unwrap().get_mentions_state().into()
}

/// Force a panic for test purposes
pub fn debug_panic(self: &Arc<Self>) {
#[cfg(debug_assertions)]
Expand Down
18 changes: 18 additions & 0 deletions bindings/wysiwyg-ffi/src/ffi_mentions_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[derive(uniffi::Record)]
pub struct MentionsState {
pub user_ids: Vec<String>,
pub room_ids: Vec<String>,
pub room_aliases: Vec<String>,
pub has_at_room_mention: bool,
}

impl From<wysiwyg::MentionsState> for MentionsState {
fn from(value: wysiwyg::MentionsState) -> Self {
Self {
user_ids: value.user_ids.into_iter().collect(),
room_ids: value.room_ids.into_iter().collect(),
room_aliases: value.room_aliases.into_iter().collect(),
has_at_room_mention: value.has_at_room_mention,
}
}
}
2 changes: 2 additions & 0 deletions bindings/wysiwyg-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mod ffi_composer_state;
mod ffi_composer_update;
mod ffi_dom_creation_error;
mod ffi_link_actions;
mod ffi_mentions_state;
mod ffi_menu_action;
mod ffi_menu_state;
mod ffi_pattern_key;
Expand All @@ -38,6 +39,7 @@ pub use crate::ffi_composer_state::ComposerState;
pub use crate::ffi_composer_update::ComposerUpdate;
pub use crate::ffi_dom_creation_error::DomCreationError;
pub use crate::ffi_link_actions::LinkAction;
pub use crate::ffi_mentions_state::MentionsState;
pub use crate::ffi_menu_action::MenuAction;
pub use crate::ffi_menu_state::MenuState;
pub use crate::ffi_pattern_key::PatternKey;
Expand Down
2 changes: 1 addition & 1 deletion crates/matrix_mentions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@

mod mention;

pub use crate::mention::{Mention, MentionKind};
pub use crate::mention::{Mention, MentionKind, RoomIdentificationType};
64 changes: 52 additions & 12 deletions crates/matrix_mentions/src/mention.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,22 @@ pub struct Mention {

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MentionKind {
Room,
Room(RoomIdentificationType),
User,
}

impl MentionKind {
pub fn is_room(&self) -> bool {
matches!(self, MentionKind::Room(_))
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RoomIdentificationType {
Id,
Alias,
}

impl Mention {
fn new(
uri: String,
Expand Down Expand Up @@ -134,17 +146,24 @@ impl Mention {
fn from_room(room_uri: &str) -> Option<Mention> {
// In all cases, use the alias/room ID being linked to as the
// anchor’s text.
let room_id_type: RoomIdentificationType;
let text = match parse_matrix_id(room_uri)? {
MatrixId::Room(room_id) => room_id.to_string(),
MatrixId::RoomAlias(room_alias) => room_alias.to_string(),
MatrixId::Room(room_id) => {
room_id_type = RoomIdentificationType::Id;
room_id.to_string()
}
MatrixId::RoomAlias(room_alias) => {
room_id_type = RoomIdentificationType::Alias;
room_alias.to_string()
}
_ => return None,
};

Some(Mention::new(
room_uri.to_string(),
text.clone(),
text,
MentionKind::Room,
MentionKind::Room(room_id_type),
))
}
}
Expand Down Expand Up @@ -200,7 +219,7 @@ fn parse_external_id(uri: &str) -> Result<MatrixToUri, IdParseError> {
mod test {
use ruma_common::{MatrixToUri, MatrixUri};

use crate::mention::{Mention, MentionKind};
use crate::mention::{Mention, MentionKind, RoomIdentificationType};

#[test]
fn parse_uri_matrix_to_valid_user() {
Expand Down Expand Up @@ -232,7 +251,10 @@ mod test {
assert_eq!(parsed.uri(), uri);
assert_eq!(parsed.mx_id(), "!roomid:example.org");
assert_eq!(parsed.display_text(), "!roomid:example.org");
assert_eq!(parsed.kind(), &MentionKind::Room);
assert_eq!(
parsed.kind(),
&MentionKind::Room(RoomIdentificationType::Id)
);
}

#[test]
Expand All @@ -243,7 +265,10 @@ mod test {
assert_eq!(parsed.uri(), uri);
assert_eq!(parsed.mx_id(), "!roomid:example.org");
assert_eq!(parsed.display_text(), "!roomid:example.org");
assert_eq!(parsed.kind(), &MentionKind::Room);
assert_eq!(
parsed.kind(),
&MentionKind::Room(RoomIdentificationType::Id)
);
}

#[test]
Expand All @@ -254,7 +279,10 @@ mod test {
assert_eq!(parsed.uri(), uri);
assert_eq!(parsed.mx_id(), "#room:example.org");
assert_eq!(parsed.display_text(), "#room:example.org");
assert_eq!(parsed.kind(), &MentionKind::Room);
assert_eq!(
parsed.kind(),
&MentionKind::Room(RoomIdentificationType::Alias)
);
}

#[test]
Expand All @@ -265,7 +293,10 @@ mod test {
assert_eq!(parsed.uri(), uri);
assert_eq!(parsed.mx_id(), "#room:example.org");
assert_eq!(parsed.display_text(), "#room:example.org");
assert_eq!(parsed.kind(), &MentionKind::Room);
assert_eq!(
parsed.kind(),
&MentionKind::Room(RoomIdentificationType::Alias)
);
}

#[test]
Expand Down Expand Up @@ -319,7 +350,10 @@ mod test {
assert_eq!(parsed.uri(), uri);
assert_eq!(parsed.mx_id(), "!roomid:example.org");
assert_eq!(parsed.display_text(), "!roomid:example.org");
assert_eq!(parsed.kind(), &MentionKind::Room);
assert_eq!(
parsed.kind(),
&MentionKind::Room(RoomIdentificationType::Id)
);
}

#[test]
Expand Down Expand Up @@ -347,7 +381,10 @@ mod test {
assert_eq!(parsed.uri(), uri);
assert_eq!(parsed.mx_id(), "!room:example.org");
assert_eq!(parsed.display_text(), "!room:example.org"); // note the display_text is overridden
assert_eq!(parsed.kind(), &MentionKind::Room);
assert_eq!(
parsed.kind(),
&MentionKind::Room(RoomIdentificationType::Id)
);
}

#[test]
Expand All @@ -361,7 +398,10 @@ mod test {
assert_eq!(parsed.uri(), uri);
assert_eq!(parsed.mx_id(), "#room:example.org");
assert_eq!(parsed.display_text(), "#room:example.org"); // note the display_text is overridden
assert_eq!(parsed.kind(), &MentionKind::Room);
assert_eq!(
parsed.kind(),
&MentionKind::Room(RoomIdentificationType::Alias)
);
}

#[test]
Expand Down
43 changes: 40 additions & 3 deletions crates/wysiwyg/src/composer_model/mentions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,52 @@
// limitations under the License.

use crate::{
dom::{nodes::MentionNode, DomLocation},
ComposerModel, ComposerUpdate, DomNode, Location, SuggestionPattern,
UnicodeString,
dom::{
nodes::{MentionNode, MentionNodeKind},
DomLocation,
},
ComposerModel, ComposerUpdate, DomNode, Location, MentionsState,
SuggestionPattern, UnicodeString,
};

impl<S> ComposerModel<S>
where
S: UnicodeString,
{
/// Returns the current mentions state of the content of the RTE editor.
pub fn get_mentions_state(&self) -> MentionsState {
let mut mentions_state = MentionsState::default();
for node in self.state.dom.iter_mentions() {
match node.kind() {
MentionNodeKind::AtRoom => {
mentions_state.has_at_room_mention = true
}
MentionNodeKind::MatrixUri { mention } => match mention.kind() {
matrix_mentions::MentionKind::Room(id_type) => {
match id_type {
matrix_mentions::RoomIdentificationType::Id => {
mentions_state
.room_ids
.insert(mention.mx_id().to_string());
}
matrix_mentions::RoomIdentificationType::Alias => {
mentions_state
.room_aliases
.insert(mention.mx_id().to_string());
}
}
}
matrix_mentions::MentionKind::User => {
mentions_state
.user_ids
.insert(mention.mx_id().to_string());
}
},
}
}
mentions_state
}

/// Checks to see if the mention should be inserted and also if the mention can be created.
/// If both of these checks are passed it will remove the suggestion and then insert a mention.
pub fn insert_mention_at_suggestion(
Expand Down
8 changes: 7 additions & 1 deletion crates/wysiwyg/src/dom/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{DomHandle, DomNode, UnicodeString};
use std::collections::HashSet;

use super::{
nodes::{ContainerNode, TextNode},
nodes::{ContainerNode, MentionNode, TextNode},
Dom,
};

Expand All @@ -48,6 +48,12 @@ where
self.iter().filter_map(DomNode::as_container)
}

/// Returns an iterator over all the mention nodes of this DOM, in depth-first
/// order
pub fn iter_mentions(&self) -> impl Iterator<Item = &MentionNode<S>> {
self.iter().filter_map(DomNode::as_mention)
}

/// Return an iterator over all nodes of the DOM from the passed node,
/// depth-first order (including self).
pub fn iter_from<'a>(&'a self, node: &'a DomNode<S>) -> DomNodeIterator<S> {
Expand Down
8 changes: 8 additions & 0 deletions crates/wysiwyg/src/dom/nodes/dom_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ where
}
}

pub(crate) fn as_mention(&self) -> Option<&MentionNode<S>> {
if let Self::Mention(v) = self {
Some(v)
} else {
None
}
}

pub fn kind(&self) -> DomNodeKind {
match self {
DomNode::Text(_) => DomNodeKind::Text,
Expand Down
17 changes: 8 additions & 9 deletions crates/wysiwyg/src/dom/nodes/mention_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ impl<S: UnicodeString> MentionNode<S> {
// this is now only required for us to attach a custom style attribute for web
let mut attrs = self.attributes.clone();
let data_mention_type = match mention.kind() {
MentionKind::Room => "room",
MentionKind::Room(_) => "room",
MentionKind::User => "user",
};
attrs.push((
Expand All @@ -177,12 +177,11 @@ impl<S: UnicodeString> MentionNode<S> {
attrs
};

let display_text =
if as_message && mention.kind() == &MentionKind::Room {
S::from(mention.mx_id())
} else {
self.display_text()
};
let display_text = if as_message && mention.kind().is_room() {
S::from(mention.mx_id())
} else {
self.display_text()
};

self.fmt_tag_open(tag, formatter, &Some(attributes));
formatter.push(display_text);
Expand Down Expand Up @@ -286,7 +285,7 @@ where
// For a mention in a message, display the `mx_id` for a room mention, `display_text` otherwise
let text = match this.kind() {
MentionNodeKind::MatrixUri { mention }
if mention.kind() == &MentionKind::Room =>
if mention.kind().is_room() =>
{
S::from(mention.mx_id())
}
Expand All @@ -305,7 +304,7 @@ where
match this.kind() {
MentionNodeKind::MatrixUri { mention } => {
data_mention_type = match mention.kind() {
MentionKind::Room => "room",
MentionKind::Room(_) => "room",
MentionKind::User => "user",
};
href = mention.uri();
Expand Down
2 changes: 2 additions & 0 deletions crates/wysiwyg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod format_type;
mod link_action;
mod list_type;
mod location;
mod mentions_state;
mod menu_action;
mod menu_state;
mod pattern_key;
Expand Down Expand Up @@ -51,6 +52,7 @@ pub use crate::link_action::LinkAction;
pub use crate::link_action::LinkActionUpdate;
pub use crate::list_type::ListType;
pub use crate::location::Location;
pub use crate::mentions_state::MentionsState;
pub use crate::menu_action::MenuAction;
pub use crate::menu_action::MenuActionSuggestion;
pub use crate::menu_state::MenuState;
Expand Down
23 changes: 23 additions & 0 deletions crates/wysiwyg/src/mentions_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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 std::collections::HashSet;

#[derive(Default, Debug, PartialEq, Eq)]
pub struct MentionsState {
pub user_ids: HashSet<String>,
pub room_ids: HashSet<String>,
pub room_aliases: HashSet<String>,
pub has_at_room_mention: bool,
}
Loading

0 comments on commit 9d60d40

Please sign in to comment.