mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-23 05:24:51 +00:00
fix: how to find best insert pos for richtext & expand type reverse behavior (#250)
* chore: bump loro-crdt version * fix: find best insert pos * fix: style anchors' ExpandType's reverse behavior
This commit is contained in:
parent
3a2c9523cd
commit
b5aa622554
3 changed files with 36 additions and 28 deletions
|
@ -63,6 +63,13 @@ impl LoroValue {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_false(&self) -> bool {
|
||||
match self {
|
||||
LoroValue::Bool(b) => !*b,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_depth(&self) -> usize {
|
||||
let mut max_depth = 0;
|
||||
let mut value_depth_pairs = vec![(self, 0)];
|
||||
|
|
|
@ -121,6 +121,8 @@ impl Ord for StyleOp {
|
|||
}
|
||||
}
|
||||
|
||||
/// TODO: We can remove this type already
|
||||
///
|
||||
/// A compact representation of a rich text style config.
|
||||
///
|
||||
/// Note: we assume style with the same key has the same `Mergeable` and `isContainer` value.
|
||||
|
@ -128,11 +130,11 @@ impl Ord for StyleOp {
|
|||
/// - 0 (1st bit)
|
||||
/// - Expand Before (2nd bit): when inserting new text before this style, whether the new text should inherit this style.
|
||||
/// - Expand After (3rd bit): when inserting new text after this style, whether the new text should inherit this style.
|
||||
/// - Delete (4th bit): whether this is used to remove a style from a range.
|
||||
/// - 0 (5th bit): whether the style also store other data in a associated map container with the same OpID.
|
||||
/// - 0 (4th bit):
|
||||
/// - 0 (5th bit):
|
||||
/// - 0 (6th bit)
|
||||
/// - 0 (7th bit)
|
||||
/// - isAlive (8th bit): always 1 unless the style is garbage collected. If this is 0, all other bits should be 0 as well.
|
||||
/// - 0 (8th bit):
|
||||
#[derive(Default, Clone, Copy, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct TextStyleInfoFlag {
|
||||
data: u8,
|
||||
|
@ -151,7 +153,6 @@ impl Debug for TextStyleInfoFlag {
|
|||
|
||||
const EXPAND_BEFORE_MASK: u8 = 0b0000_0010;
|
||||
const EXPAND_AFTER_MASK: u8 = 0b0000_0100;
|
||||
const DELETE_MASK: u8 = 0b0000_1000;
|
||||
const ALIVE_MASK: u8 = 0b1000_0000;
|
||||
|
||||
/// Whether to expand the style when inserting new text around it.
|
||||
|
@ -198,19 +199,22 @@ impl ExpandType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create reversed expand type.
|
||||
/// Toggle expand type between for deletion and for creation
|
||||
///
|
||||
/// Before -> After
|
||||
/// After -> Before
|
||||
/// For a style that expand after, when we delete the style, we need to have another style that expands after to nullify it,
|
||||
/// so that the expand behavior is not changed.
|
||||
///
|
||||
/// Before -> Before
|
||||
/// After -> After
|
||||
/// Both -> None
|
||||
/// None -> Both
|
||||
///
|
||||
/// Because the creation of text styles and the deletion of the text styles have reversed expand type.
|
||||
/// This method is useful to convert between the two
|
||||
pub fn reverse(self) -> Self {
|
||||
pub const fn reverse(self) -> Self {
|
||||
match self {
|
||||
ExpandType::Before => ExpandType::After,
|
||||
ExpandType::After => ExpandType::Before,
|
||||
ExpandType::Before => ExpandType::Before,
|
||||
ExpandType::After => ExpandType::After,
|
||||
ExpandType::Both => ExpandType::None,
|
||||
ExpandType::None => ExpandType::Both,
|
||||
}
|
||||
|
@ -220,16 +224,25 @@ impl ExpandType {
|
|||
impl TextStyleInfoFlag {
|
||||
/// When inserting new text around this style, prefer inserting after it.
|
||||
#[inline(always)]
|
||||
pub fn expand_before(self) -> bool {
|
||||
pub const fn expand_before(self) -> bool {
|
||||
self.data & EXPAND_BEFORE_MASK != 0
|
||||
}
|
||||
|
||||
/// When inserting new text around this style, prefer inserting before it.
|
||||
#[inline(always)]
|
||||
pub fn expand_after(self) -> bool {
|
||||
pub const fn expand_after(self) -> bool {
|
||||
self.data & EXPAND_AFTER_MASK != 0
|
||||
}
|
||||
|
||||
pub const fn expand_type(self) -> ExpandType {
|
||||
match (self.expand_before(), self.expand_after()) {
|
||||
(true, true) => ExpandType::Both,
|
||||
(true, false) => ExpandType::Before,
|
||||
(false, true) => ExpandType::After,
|
||||
(false, false) => ExpandType::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// This method tells that when we can insert text before/after this style anchor, whether we insert the new text before the anchor.
|
||||
#[inline]
|
||||
pub fn prefer_insert_before(self, anchor_type: AnchorType) -> bool {
|
||||
|
@ -257,23 +270,9 @@ impl TextStyleInfoFlag {
|
|||
TextStyleInfoFlag { data }
|
||||
}
|
||||
|
||||
pub const fn is_dead(self) -> bool {
|
||||
debug_assert!((self.data & ALIVE_MASK != 0) || self.data == 0);
|
||||
(self.data & ALIVE_MASK) == 0
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub const fn to_delete(self) -> Self {
|
||||
let mut data = self.data;
|
||||
if data & DELETE_MASK > 0 {
|
||||
return Self { data };
|
||||
}
|
||||
|
||||
// set is_delete
|
||||
data |= DELETE_MASK;
|
||||
// invert expand type
|
||||
data ^= EXPAND_AFTER_MASK | EXPAND_BEFORE_MASK;
|
||||
Self { data }
|
||||
TextStyleInfoFlag::new(self.expand_type().reverse())
|
||||
}
|
||||
|
||||
pub const BOLD: TextStyleInfoFlag = TextStyleInfoFlag::new(ExpandType::After);
|
||||
|
|
|
@ -1527,7 +1527,9 @@ impl RichtextState {
|
|||
};
|
||||
|
||||
visited.push((style, anchor_type, iter, entity_index));
|
||||
if anchor_type == AnchorType::Start {
|
||||
if anchor_type == AnchorType::Start
|
||||
&& (!style.value.is_null() || !style.value.is_false())
|
||||
{
|
||||
// case 1. should be before this anchor
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue