Add Markdown Preview Toggle (#15215)

Add a "Preview Markdown" button to the quick action bar when in a
markdown editor.

While it isn't my favorite, I went with the basic eye icon to be a bit
more generic so we can extend this control to allow opening other
previews such as SVGs like @jansol mentioned.

![CleanShot 2024-07-26 at 11 02
16@2x](https://github.com/user-attachments/assets/415963ce-d19e-432d-b8c2-37e7c6e52683)


https://github.com/user-attachments/assets/5980272c-eab9-4f69-86b6-0c593c25b525

---

Release Notes:

- Added a button to preview Markdown files in the toolbar.
`Option|Alt+Click` will open the preview to the side.
This commit is contained in:
Nate Butler 2024-07-26 11:08:42 -04:00 committed by GitHub
parent 73d682c010
commit 05825e9804
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 93 additions and 21 deletions

1
Cargo.lock generated
View File

@ -8270,6 +8270,7 @@ dependencies = [
"assistant",
"editor",
"gpui",
"markdown_preview",
"repl",
"search",
"settings",

1
assets/icons/eye.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-eye"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg>

After

Width:  |  Height:  |  Size: 358 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-code"><path d="M10 12.5 8 15l2 2.5"/><path d="m14 12.5 2 2.5-2 2.5"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"/></svg>

After

Width:  |  Height:  |  Size: 388 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-text"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>

After

Width:  |  Height:  |  Size: 384 B

View File

@ -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<Workspace>,
) -> Option<View<Editor>> {
@ -278,7 +278,7 @@ impl MarkdownPreviewView {
}
}
fn is_markdown_file<V>(editor: &View<Editor>, cx: &mut ViewContext<V>) -> bool {
pub fn is_markdown_file<V>(editor: &View<Editor>, cx: &mut ViewContext<V>) -> bool {
let language = editor.read(cx).buffer().read(cx).language_at(0, cx);
language
.map(|l| l.name().as_ref() == "Markdown")

View File

@ -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]

View File

@ -21,16 +21,18 @@ use workspace::{
};
mod repl_menu;
mod toggle_markdown_preview;
pub struct QuickActionBar {
buffer_search_bar: View<BufferSearchBar>,
repl_menu: Option<View<ContextMenu>>,
toggle_settings_menu: Option<View<ContextMenu>>,
toggle_selections_menu: Option<View<ContextMenu>>,
active_item: Option<Box<dyn ItemHandle>>,
_inlay_hints_enabled_subscription: Option<Subscription>,
workspace: WeakView<Workspace>,
active_item: Option<Box<dyn ItemHandle>>,
buffer_search_bar: View<BufferSearchBar>,
platform_style: PlatformStyle,
repl_menu: Option<View<ContextMenu>>,
show: bool,
toggle_selections_menu: Option<View<ContextMenu>>,
toggle_settings_menu: Option<View<ContextMenu>>,
workspace: WeakView<Workspace>,
}
impl QuickActionBar {
@ -40,14 +42,15 @@ impl QuickActionBar {
cx: &mut ViewContext<Self>,
) -> 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::<SettingsStore>(|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))

View File

@ -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<Workspace>,
cx: &mut ViewContext<Self>,
) -> Option<AnyElement> {
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())
}
}

View File

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