diff --git a/Cargo.lock b/Cargo.lock
index dc9253c2d6..08f813f835 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8270,6 +8270,7 @@ dependencies = [
"assistant",
"editor",
"gpui",
+ "markdown_preview",
"repl",
"search",
"settings",
diff --git a/assets/icons/eye.svg b/assets/icons/eye.svg
new file mode 100644
index 0000000000..21e3d3ba63
--- /dev/null
+++ b/assets/icons/eye.svg
@@ -0,0 +1 @@
+
diff --git a/assets/icons/file_code.svg b/assets/icons/file_code.svg
new file mode 100644
index 0000000000..0a15da7705
--- /dev/null
+++ b/assets/icons/file_code.svg
@@ -0,0 +1 @@
+
diff --git a/assets/icons/file_text.svg b/assets/icons/file_text.svg
new file mode 100644
index 0000000000..7c602f2ac7
--- /dev/null
+++ b/assets/icons/file_text.svg
@@ -0,0 +1 @@
+
diff --git a/crates/markdown_preview/src/markdown_preview_view.rs b/crates/markdown_preview/src/markdown_preview_view.rs
index 9c547ee665..802e7e2b87 100644
--- a/crates/markdown_preview/src/markdown_preview_view.rs
+++ b/crates/markdown_preview/src/markdown_preview_view.rs
@@ -99,7 +99,7 @@ impl MarkdownPreviewView {
.and_then(|view| pane.index_for_item(&view))
}
- fn resolve_active_item_as_markdown_editor(
+ pub fn resolve_active_item_as_markdown_editor(
workspace: &Workspace,
cx: &mut ViewContext,
) -> Option> {
@@ -278,7 +278,7 @@ impl MarkdownPreviewView {
}
}
- fn is_markdown_file(editor: &View, cx: &mut ViewContext) -> bool {
+ pub fn is_markdown_file(editor: &View, cx: &mut ViewContext) -> bool {
let language = editor.read(cx).buffer().read(cx).language_at(0, cx);
language
.map(|l| l.name().as_ref() == "Markdown")
diff --git a/crates/quick_action_bar/Cargo.toml b/crates/quick_action_bar/Cargo.toml
index e5574a83f8..6f0d01f2a3 100644
--- a/crates/quick_action_bar/Cargo.toml
+++ b/crates/quick_action_bar/Cargo.toml
@@ -16,12 +16,13 @@ doctest = false
assistant.workspace = true
editor.workspace = true
gpui.workspace = true
+markdown_preview.workspace = true
+repl.workspace = true
search.workspace = true
settings.workspace = true
ui.workspace = true
util.workspace = true
workspace.workspace = true
-repl.workspace = true
zed_actions.workspace = true
[dev-dependencies]
diff --git a/crates/quick_action_bar/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs
index 89ef4ac9d1..607cef72d3 100644
--- a/crates/quick_action_bar/src/quick_action_bar.rs
+++ b/crates/quick_action_bar/src/quick_action_bar.rs
@@ -21,16 +21,18 @@ use workspace::{
};
mod repl_menu;
+mod toggle_markdown_preview;
pub struct QuickActionBar {
- buffer_search_bar: View,
- repl_menu: Option>,
- toggle_settings_menu: Option>,
- toggle_selections_menu: Option>,
- active_item: Option>,
_inlay_hints_enabled_subscription: Option,
- workspace: WeakView,
+ active_item: Option>,
+ buffer_search_bar: View,
+ platform_style: PlatformStyle,
+ repl_menu: Option>,
show: bool,
+ toggle_selections_menu: Option>,
+ toggle_settings_menu: Option>,
+ workspace: WeakView,
}
impl QuickActionBar {
@@ -40,14 +42,15 @@ impl QuickActionBar {
cx: &mut ViewContext,
) -> Self {
let mut this = Self {
- buffer_search_bar,
- toggle_settings_menu: None,
- toggle_selections_menu: None,
- repl_menu: None,
- active_item: None,
_inlay_hints_enabled_subscription: None,
- workspace: workspace.weak_handle(),
+ active_item: None,
+ buffer_search_bar,
+ platform_style: PlatformStyle::platform(),
+ repl_menu: None,
show: true,
+ toggle_selections_menu: None,
+ toggle_settings_menu: None,
+ workspace: workspace.weak_handle(),
};
this.apply_settings(cx);
cx.observe_global::(|this, cx| this.apply_settings(cx))
@@ -300,22 +303,19 @@ impl Render for QuickActionBar {
h_flex()
.id("quick action bar")
- .gap(Spacing::Large.rems(cx))
+ .gap(Spacing::XXLarge.rems(cx))
.child(
h_flex()
.gap(Spacing::Medium.rems(cx))
.children(self.render_repl_menu(cx))
+ .children(self.render_toggle_markdown_preview(self.workspace.clone(), cx))
+ .children(search_button)
.when(
AssistantSettings::get_global(cx).enabled
&& AssistantSettings::get_global(cx).button,
|bar| bar.child(assistant_button),
),
)
- .child(
- h_flex()
- .gap(Spacing::Medium.rems(cx))
- .children(search_button),
- )
.child(
h_flex()
.gap(Spacing::Medium.rems(cx))
diff --git a/crates/quick_action_bar/src/toggle_markdown_preview.rs b/crates/quick_action_bar/src/toggle_markdown_preview.rs
new file mode 100644
index 0000000000..3498093471
--- /dev/null
+++ b/crates/quick_action_bar/src/toggle_markdown_preview.rs
@@ -0,0 +1,61 @@
+use gpui::{AnyElement, WeakView};
+use markdown_preview::{
+ markdown_preview_view::MarkdownPreviewView, OpenPreview, OpenPreviewToTheSide,
+};
+use ui::{prelude::*, IconButtonShape, Tooltip};
+use workspace::Workspace;
+
+use crate::QuickActionBar;
+
+impl QuickActionBar {
+ pub fn render_toggle_markdown_preview(
+ &self,
+ workspace: WeakView,
+ cx: &mut ViewContext,
+ ) -> Option {
+ let mut active_editor_is_markdown = false;
+
+ if let Some(workspace) = self.workspace.upgrade() {
+ workspace.update(cx, |workspace, cx| {
+ active_editor_is_markdown =
+ MarkdownPreviewView::resolve_active_item_as_markdown_editor(workspace, cx)
+ .is_some();
+ });
+ }
+
+ if !active_editor_is_markdown {
+ return None;
+ }
+
+ let tooltip_meta = match self.platform_style {
+ PlatformStyle::Mac => "Option+Click to open in a split",
+ _ => "Alt+Click to open in a split",
+ };
+
+ let button = IconButton::new("toggle-markdown-preview", IconName::Eye)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .style(ButtonStyle::Subtle)
+ .tooltip(move |cx| {
+ Tooltip::with_meta(
+ "Preview Markdown",
+ Some(&markdown_preview::OpenPreview),
+ tooltip_meta,
+ cx,
+ )
+ })
+ .on_click(move |_, cx| {
+ if let Some(workspace) = workspace.upgrade() {
+ workspace.update(cx, |_, cx| {
+ if cx.modifiers().alt {
+ cx.dispatch_action(Box::new(OpenPreviewToTheSide));
+ } else {
+ cx.dispatch_action(Box::new(OpenPreview));
+ }
+ });
+ }
+ });
+
+ Some(button.into_any_element())
+ }
+}
diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs
index 2b5ea51767..dd3db7e6db 100644
--- a/crates/ui/src/components/icon.rs
+++ b/crates/ui/src/components/icon.rs
@@ -158,6 +158,7 @@ pub enum IconName {
Exit,
ExpandVertical,
ExternalLink,
+ Eye,
File,
FileDoc,
FileGeneric,
@@ -166,6 +167,8 @@ pub enum IconName {
FileRust,
FileToml,
FileTree,
+ FileText,
+ FileCode,
Filter,
Folder,
FolderOpen,
@@ -309,6 +312,7 @@ impl IconName {
IconName::Exit => "icons/exit.svg",
IconName::ExpandVertical => "icons/expand_vertical.svg",
IconName::ExternalLink => "icons/external_link.svg",
+ IconName::Eye => "icons/eye.svg",
IconName::File => "icons/file.svg",
IconName::FileDoc => "icons/file_icons/book.svg",
IconName::FileGeneric => "icons/file_icons/file.svg",
@@ -317,6 +321,8 @@ impl IconName {
IconName::FileRust => "icons/file_icons/rust.svg",
IconName::FileToml => "icons/file_icons/toml.svg",
IconName::FileTree => "icons/project.svg",
+ IconName::FileCode => "icons/file_code.svg",
+ IconName::FileText => "icons/file_text.svg",
IconName::Filter => "icons/filter.svg",
IconName::Folder => "icons/file_icons/folder.svg",
IconName::FolderOpen => "icons/file_icons/folder_open.svg",