From b3a67c988f9d28a009086952d46fc8c977ad028c Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Thu, 7 May 2026 11:31:37 +0200 Subject: [PATCH] markdown_preview: Implement reload (#56016) If you implement can_save, you need to also support reload. Fix a bug introduced in #53236 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed missing reload implementation for markdown preview. --- .../src/markdown_preview_view.rs | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/crates/markdown_preview/src/markdown_preview_view.rs b/crates/markdown_preview/src/markdown_preview_view.rs index 76b46a520d539178f514dd36b9708373cddc0bc4..333a1b2a2b3ceadf3ef4d3fd1e99738b3a172ea8 100644 --- a/crates/markdown_preview/src/markdown_preview_view.rs +++ b/crates/markdown_preview/src/markdown_preview_view.rs @@ -975,6 +975,16 @@ impl Item for MarkdownPreviewView { .unwrap_or_else(|| Task::ready(Ok(()))) } + fn reload( + &mut self, + _project: Entity, + _window: &mut Window, + _cx: &mut Context, + ) -> Task> { + // The preview is not the owner of the source editor's buffer, so force-closing it should not discard editor changes. + Task::ready(Ok(())) + } + fn to_item_events(_event: &Self::Event, _f: &mut dyn FnMut(workspace::item::ItemEvent)) {} fn buffer_kind(&self, _cx: &App) -> ItemBufferKind { @@ -1354,6 +1364,92 @@ mod tests { ); } + #[gpui::test] + async fn force_closing_preview_preserves_source_editor_changes(cx: &mut TestAppContext) { + let app_state = init_test(cx); + app_state + .fs + .as_fake() + .insert_tree( + path!("/dir"), + json!({ + "todo.md": "- [ ] Finish work\n" + }), + ) + .await; + + cx.update(|cx| { + open_paths( + &[PathBuf::from(path!("/dir/todo.md"))], + app_state.clone(), + workspace::OpenOptions::default(), + cx, + ) + }) + .await + .unwrap(); + + let multi_workspace = cx.update(|cx| cx.windows()[0].downcast::().unwrap()); + let (preview, editor) = multi_workspace + .update(cx, |multi_workspace, window, cx| { + let workspace = multi_workspace.workspace().clone(); + let editor: Entity = workspace + .read(cx) + .active_item(cx) + .and_then(|item| item.act_as::(cx)) + .unwrap(); + + let preview = workspace.update(cx, |workspace, cx| { + let preview = MarkdownPreviewView::create_markdown_view( + workspace, + editor.clone(), + window, + cx, + ); + workspace.active_pane().update(cx, |pane, cx| { + pane.add_item(Box::new(preview.clone()), true, true, None, window, cx) + }); + preview + }); + + (preview, editor) + }) + .unwrap(); + cx.run_until_parked(); + + multi_workspace + .update(cx, |_, window, cx| { + let view_handle = preview.downgrade(); + assert!(preview.read(cx).focus_handle.contains_focused(window, cx)); + MarkdownPreviewView::apply_checkbox_toggle_to_editor(&editor, 2..5, true, cx); + MarkdownPreviewView::refresh_preview(view_handle, window, cx); + }) + .unwrap(); + + assert_eq!( + editor.read_with(cx, |editor, cx| editor.buffer().read(cx).read(cx).text()), + "- [x] Finish work\n" + ); + + let close_task = multi_workspace + .update(cx, |multi_workspace, window, cx| { + multi_workspace.workspace().update(cx, |workspace, cx| { + workspace.active_pane().update(cx, |pane, cx| { + pane.close_item_by_id(preview.entity_id(), SaveIntent::Skip, window, cx) + }) + }) + }) + .unwrap(); + + close_task.await.unwrap(); + cx.run_until_parked(); + + assert_eq!( + editor.read_with(cx, |editor, cx| editor.buffer().read(cx).read(cx).text()), + "- [x] Finish work\n" + ); + } + fn init_test(cx: &mut TestAppContext) -> Arc { cx.update(|cx| { let state = AppState::test(cx);