Fix circular reference issue around PopoverMenu again (#44084)

feeiyu created

Follow up to https://github.com/zed-industries/zed/pull/42351

Release Notes:

- N/A

Change summary

crates/agent_ui/src/acp/mode_selector.rs      |  5 +++--
crates/extensions_ui/src/extensions_ui.rs     | 18 ++++++++++--------
crates/language_tools/src/lsp_log_view.rs     |  4 ++--
crates/language_tools/src/syntax_tree_view.rs | 14 +++++++++-----
4 files changed, 24 insertions(+), 17 deletions(-)

Detailed changes

crates/agent_ui/src/acp/mode_selector.rs 🔗

@@ -161,7 +161,7 @@ impl Render for ModeSelector {
             .map(|mode| mode.name.clone())
             .unwrap_or_else(|| "Unknown".into());
 
-        let this = cx.entity();
+        let this = cx.weak_entity();
 
         let icon = if self.menu_handle.is_deployed() {
             IconName::ChevronUp
@@ -222,7 +222,8 @@ impl Render for ModeSelector {
                 y: px(-2.0),
             })
             .menu(move |window, cx| {
-                Some(this.update(cx, |this, cx| this.build_context_menu(window, cx)))
+                this.update(cx, |this, cx| this.build_context_menu(window, cx))
+                    .ok()
             })
     }
 }

crates/extensions_ui/src/extensions_ui.rs 🔗

@@ -739,7 +739,7 @@ impl ExtensionsPage {
         extension: &ExtensionMetadata,
         cx: &mut Context<Self>,
     ) -> ExtensionCard {
-        let this = cx.entity();
+        let this = cx.weak_entity();
         let status = Self::extension_status(&extension.id, cx);
         let has_dev_extension = Self::dev_extension_exists(&extension.id, cx);
 
@@ -889,13 +889,15 @@ impl ExtensionsPage {
                                     y: px(2.0),
                                 })
                                 .menu(move |window, cx| {
-                                    Some(Self::render_remote_extension_context_menu(
-                                        &this,
-                                        extension_id.clone(),
-                                        authors.clone(),
-                                        window,
-                                        cx,
-                                    ))
+                                    this.upgrade().map(|this| {
+                                        Self::render_remote_extension_context_menu(
+                                            &this,
+                                            extension_id.clone(),
+                                            authors.clone(),
+                                            window,
+                                            cx,
+                                        )
+                                    })
                                 }),
                             ),
                     ),

crates/language_tools/src/lsp_log_view.rs 🔗

@@ -937,7 +937,7 @@ impl Render for LspLogToolbarItemView {
             })
             .collect();
 
-        let log_toolbar_view = cx.entity();
+        let log_toolbar_view = cx.weak_entity();
 
         let lsp_menu = PopoverMenu::new("LspLogView")
             .anchor(Corner::TopLeft)
@@ -1021,7 +1021,7 @@ impl Render for LspLogToolbarItemView {
                         .icon_color(Color::Muted),
                 )
                 .menu(move |window, cx| {
-                    let log_toolbar_view = log_toolbar_view.clone();
+                    let log_toolbar_view = log_toolbar_view.upgrade()?;
                     let log_view = log_view.clone();
                     Some(ContextMenu::build(window, cx, move |this, window, _| {
                         this.entry(

crates/language_tools/src/syntax_tree_view.rs 🔗

@@ -614,13 +614,14 @@ impl SyntaxTreeToolbarItemView {
         let active_layer = buffer_state.active_layer.clone()?;
         let active_buffer = buffer_state.buffer.read(cx).snapshot();
 
-        let view = cx.entity();
+        let view = cx.weak_entity();
         Some(
             PopoverMenu::new("Syntax Tree")
                 .trigger(Self::render_header(&active_layer))
                 .menu(move |window, cx| {
-                    ContextMenu::build(window, cx, |mut menu, window, _| {
+                    ContextMenu::build(window, cx, |mut menu, _, _| {
                         for (layer_ix, layer) in active_buffer.syntax_layers().enumerate() {
+                            let view = view.clone();
                             menu = menu.entry(
                                 format!(
                                     "{} {}",
@@ -628,9 +629,12 @@ impl SyntaxTreeToolbarItemView {
                                     format_node_range(layer.node())
                                 ),
                                 None,
-                                window.handler_for(&view, move |view, window, cx| {
-                                    view.select_layer(layer_ix, window, cx);
-                                }),
+                                move |window, cx| {
+                                    view.update(cx, |view, cx| {
+                                        view.select_layer(layer_ix, window, cx);
+                                    })
+                                    .ok();
+                                },
                             );
                         }
                         menu