Fix view handle leaks in ListState callbacks

Max Brunsfeld created

Change summary

crates/collab_ui2/src/chat_panel.rs         | 10 +++++++---
crates/collab_ui2/src/collab_panel.rs       |  9 ++++++---
crates/collab_ui2/src/notification_panel.rs | 12 ++++++------
3 files changed, 19 insertions(+), 12 deletions(-)

Detailed changes

crates/collab_ui2/src/chat_panel.rs 🔗

@@ -92,11 +92,15 @@ impl ChatPanel {
 
         let workspace_handle = workspace.weak_handle();
 
-        cx.build_view(|cx| {
-            let view: View<ChatPanel> = cx.view().clone();
+        cx.build_view(|cx: &mut ViewContext<Self>| {
+            let view = cx.view().downgrade();
             let message_list =
                 ListState::new(0, gpui::ListAlignment::Bottom, px(1000.), move |ix, cx| {
-                    view.update(cx, |view, cx| view.render_message(ix, cx))
+                    if let Some(view) = view.upgrade() {
+                        view.update(cx, |view, cx| view.render_message(ix, cx))
+                    } else {
+                        div().into_any()
+                    }
                 });
 
             message_list.set_scroll_handler(cx.listener(|this, event: &ListScrollEvent, cx| {

crates/collab_ui2/src/collab_panel.rs 🔗

@@ -178,8 +178,6 @@ enum ListEntry {
 impl CollabPanel {
     pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
         cx.build_view(|cx| {
-            let view = cx.view().clone();
-
             let filter_editor = cx.build_view(|cx| {
                 let mut editor = Editor::single_line(cx);
                 editor.set_placeholder_text("Filter...", cx);
@@ -219,9 +217,14 @@ impl CollabPanel {
             })
             .detach();
 
+            let view = cx.view().downgrade();
             let list_state =
                 ListState::new(0, gpui::ListAlignment::Top, px(1000.), move |ix, cx| {
-                    view.update(cx, |view, cx| view.render_list_entry(ix, cx))
+                    if let Some(view) = view.upgrade() {
+                        view.update(cx, |view, cx| view.render_list_entry(ix, cx))
+                    } else {
+                        div().into_any()
+                    }
                 });
 
             let mut this = Self {

crates/collab_ui2/src/notification_panel.rs 🔗

@@ -88,8 +88,6 @@ impl NotificationPanel {
         let workspace_handle = workspace.weak_handle();
 
         cx.build_view(|cx: &mut ViewContext<Self>| {
-            let view = cx.view().clone();
-
             let mut status = client.status();
             cx.spawn(|this, mut cx| async move {
                 while let Some(_) = status.next().await {
@@ -105,12 +103,14 @@ impl NotificationPanel {
             })
             .detach();
 
+            let view = cx.view().downgrade();
             let notification_list =
                 ListState::new(0, ListAlignment::Top, px(1000.), move |ix, cx| {
-                    view.update(cx, |this, cx| {
-                        this.render_notification(ix, cx)
-                            .unwrap_or_else(|| div().into_any())
-                    })
+                    view.upgrade()
+                        .and_then(|view| {
+                            view.update(cx, |this, cx| this.render_notification(ix, cx))
+                        })
+                        .unwrap_or_else(|| div().into_any())
                 });
             notification_list.set_scroll_handler(cx.listener(
                 |this, event: &ListScrollEvent, cx| {