>,
disposition: BlockDisposition,
+ priority: usize,
}
pub struct BlockProperties {
@@ -92,6 +93,7 @@ pub struct BlockProperties
{
pub style: BlockStyle,
pub render: RenderBlock,
pub disposition: BlockDisposition,
+ pub priority: usize,
}
impl Debug for BlockProperties {
@@ -182,6 +184,7 @@ pub(crate) enum BlockType {
pub(crate) trait BlockLike {
fn block_type(&self) -> BlockType;
fn disposition(&self) -> BlockDisposition;
+ fn priority(&self) -> usize;
}
#[allow(clippy::large_enum_variant)]
@@ -215,6 +218,14 @@ impl BlockLike for Block {
fn disposition(&self) -> BlockDisposition {
self.disposition()
}
+
+ fn priority(&self) -> usize {
+ match self {
+ Block::Custom(block) => block.priority,
+ Block::ExcerptHeader { .. } => usize::MAX,
+ Block::ExcerptFooter { .. } => 0,
+ }
+ }
}
impl Block {
@@ -660,7 +671,10 @@ impl BlockMap {
(BlockType::Header, BlockType::Header) => Ordering::Equal,
(BlockType::Header, _) => Ordering::Less,
(_, BlockType::Header) => Ordering::Greater,
- (BlockType::Custom(a_id), BlockType::Custom(b_id)) => a_id.cmp(&b_id),
+ (BlockType::Custom(a_id), BlockType::Custom(b_id)) => block_b
+ .priority()
+ .cmp(&block_a.priority())
+ .then_with(|| a_id.cmp(&b_id)),
})
})
});
@@ -802,6 +816,7 @@ impl<'a> BlockMapWriter<'a> {
render: Arc::new(Mutex::new(block.render)),
disposition: block.disposition,
style: block.style,
+ priority: block.priority,
});
self.0.custom_blocks.insert(block_ix, new_block.clone());
self.0.custom_blocks_by_id.insert(id, new_block);
@@ -832,6 +847,7 @@ impl<'a> BlockMapWriter<'a> {
style: block.style,
render: block.render.clone(),
disposition: block.disposition,
+ priority: block.priority,
};
let new_block = Arc::new(new_block);
*block = new_block.clone();
@@ -1463,6 +1479,7 @@ mod tests {
height: 1,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()),
+ priority: 0,
},
BlockProperties {
style: BlockStyle::Fixed,
@@ -1470,6 +1487,7 @@ mod tests {
height: 2,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()),
+ priority: 0,
},
BlockProperties {
style: BlockStyle::Fixed,
@@ -1477,6 +1495,7 @@ mod tests {
height: 3,
disposition: BlockDisposition::Below,
render: Box::new(|_| div().into_any()),
+ priority: 0,
},
]);
@@ -1716,6 +1735,7 @@ mod tests {
height: 1,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()),
+ priority: 0,
},
BlockProperties {
style: BlockStyle::Fixed,
@@ -1723,6 +1743,7 @@ mod tests {
height: 2,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()),
+ priority: 0,
},
BlockProperties {
style: BlockStyle::Fixed,
@@ -1730,6 +1751,7 @@ mod tests {
height: 3,
disposition: BlockDisposition::Below,
render: Box::new(|_| div().into_any()),
+ priority: 0,
},
]);
@@ -1819,6 +1841,7 @@ mod tests {
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()),
height: 1,
+ priority: 0,
},
BlockProperties {
style: BlockStyle::Fixed,
@@ -1826,6 +1849,7 @@ mod tests {
disposition: BlockDisposition::Below,
render: Box::new(|_| div().into_any()),
height: 1,
+ priority: 0,
},
]);
@@ -1924,6 +1948,7 @@ mod tests {
height,
disposition,
render: Box::new(|_| div().into_any()),
+ priority: 0,
}
})
.collect::>();
@@ -1944,6 +1969,7 @@ mod tests {
style: props.style,
render: Box::new(|_| div().into_any()),
disposition: props.disposition,
+ priority: 0,
}));
for (block_id, props) in block_ids.into_iter().zip(block_properties) {
custom_blocks.push((block_id, props));
@@ -2014,6 +2040,7 @@ mod tests {
disposition: block.disposition,
id: *id,
height: block.height,
+ priority: block.priority,
},
)
}));
@@ -2235,6 +2262,7 @@ mod tests {
disposition: BlockDisposition,
id: CustomBlockId,
height: u32,
+ priority: usize,
},
}
@@ -2250,6 +2278,14 @@ mod tests {
fn disposition(&self) -> BlockDisposition {
self.disposition()
}
+
+ fn priority(&self) -> usize {
+ match self {
+ ExpectedBlock::Custom { priority, .. } => *priority,
+ ExpectedBlock::ExcerptHeader { .. } => usize::MAX,
+ ExpectedBlock::ExcerptFooter { .. } => 0,
+ }
+ }
}
impl ExpectedBlock {
@@ -2277,6 +2313,7 @@ mod tests {
id: block.id,
disposition: block.disposition,
height: block.height,
+ priority: block.priority,
},
Block::ExcerptHeader {
height,
diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs
index 6d973e29e4..8df833120a 100644
--- a/crates/editor/src/editor.rs
+++ b/crates/editor/src/editor.rs
@@ -9614,6 +9614,7 @@ impl Editor {
}
}),
disposition: BlockDisposition::Below,
+ priority: 0,
}],
Some(Autoscroll::fit()),
cx,
@@ -9877,6 +9878,7 @@ impl Editor {
height: message_height,
render: diagnostic_block_renderer(diagnostic, None, true, true),
disposition: BlockDisposition::Below,
+ priority: 0,
}
}),
cx,
@@ -10182,6 +10184,7 @@ impl Editor {
if let Some(autoscroll) = autoscroll {
self.request_autoscroll(autoscroll, cx);
}
+ cx.notify();
blocks
}
@@ -10196,6 +10199,7 @@ impl Editor {
if let Some(autoscroll) = autoscroll {
self.request_autoscroll(autoscroll, cx);
}
+ cx.notify();
}
pub fn replace_blocks(
@@ -10208,9 +10212,8 @@ impl Editor {
.update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
if let Some(autoscroll) = autoscroll {
self.request_autoscroll(autoscroll, cx);
- } else {
- cx.notify();
}
+ cx.notify();
}
pub fn remove_blocks(
@@ -10225,6 +10228,7 @@ impl Editor {
if let Some(autoscroll) = autoscroll {
self.request_autoscroll(autoscroll, cx);
}
+ cx.notify();
}
pub fn row_for_block(
diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs
index ba563c26ea..bdff24131b 100644
--- a/crates/editor/src/editor_tests.rs
+++ b/crates/editor/src/editor_tests.rs
@@ -3785,6 +3785,7 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
disposition: BlockDisposition::Below,
height: 1,
render: Box::new(|_| div().into_any()),
+ priority: 0,
}],
Some(Autoscroll::fit()),
cx,
diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs
index 8a386baebf..29033646b7 100644
--- a/crates/editor/src/element.rs
+++ b/crates/editor/src/element.rs
@@ -6478,6 +6478,7 @@ mod tests {
height: 3,
position: Anchor::min(),
render: Box::new(|cx| div().h(3. * cx.line_height()).into_any()),
+ priority: 0,
}],
None,
cx,
diff --git a/crates/editor/src/hunk_diff.rs b/crates/editor/src/hunk_diff.rs
index f4f9c0f8fb..2c4438eb3b 100644
--- a/crates/editor/src/hunk_diff.rs
+++ b/crates/editor/src/hunk_diff.rs
@@ -525,6 +525,7 @@ impl Editor {
.child(editor_with_deleted_text.clone())
.into_any_element()
}),
+ priority: 0,
}),
None,
cx,
diff --git a/crates/repl/src/session.rs b/crates/repl/src/session.rs
index 4fb981d85c..ba1d70020c 100644
--- a/crates/repl/src/session.rs
+++ b/crates/repl/src/session.rs
@@ -87,6 +87,7 @@ impl EditorBlock {
style: BlockStyle::Sticky,
render: Self::create_output_area_renderer(execution_view.clone(), on_close.clone()),
disposition: BlockDisposition::Below,
+ priority: 0,
};
let block_id = editor.insert_blocks([block], None, cx)[0];
diff --git a/crates/ui/src/components/button/button_like.rs b/crates/ui/src/components/button/button_like.rs
index de2557f176..3da874c04b 100644
--- a/crates/ui/src/components/button/button_like.rs
+++ b/crates/ui/src/components/button/button_like.rs
@@ -50,6 +50,7 @@ pub enum TintColor {
Accent,
Negative,
Warning,
+ Positive,
}
impl TintColor {
@@ -73,6 +74,12 @@ impl TintColor {
label_color: cx.theme().colors().text,
icon_color: cx.theme().colors().text,
},
+ TintColor::Positive => ButtonLikeStyles {
+ background: cx.theme().status().success_background,
+ border_color: cx.theme().status().success_border,
+ label_color: cx.theme().colors().text,
+ icon_color: cx.theme().colors().text,
+ },
}
}
}
@@ -83,6 +90,7 @@ impl From for Color {
TintColor::Accent => Color::Accent,
TintColor::Negative => Color::Error,
TintColor::Warning => Color::Warning,
+ TintColor::Positive => Color::Success,
}
}
}
diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs
index 9e87e8046a..40b51f616d 100644
--- a/crates/ui/src/components/icon.rs
+++ b/crates/ui/src/components/icon.rs
@@ -256,6 +256,7 @@ pub enum IconName {
TextSearch,
Trash,
TriangleRight,
+ Undo,
Update,
WholeWord,
XCircle,
@@ -419,6 +420,7 @@ impl IconName {
IconName::Trash => "icons/trash.svg",
IconName::TriangleRight => "icons/triangle_right.svg",
IconName::Update => "icons/update.svg",
+ IconName::Undo => "icons/undo.svg",
IconName::WholeWord => "icons/word_search.svg",
IconName::XCircle => "icons/error.svg",
IconName::ZedAssistant => "icons/zed_assistant.svg",