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",