Start work on subscribing to model from ChatPanel

Max Brunsfeld created

Change summary

gpui/src/elements/list.rs |  2 
zed/src/channel.rs        |  1 
zed/src/chat_panel.rs     | 44 +++++++++++++++++++++++-----------------
zed/src/workspace.rs      | 10 +-------
4 files changed, 29 insertions(+), 28 deletions(-)

Detailed changes

gpui/src/elements/list.rs 🔗

@@ -219,7 +219,7 @@ impl StateInner {
         let start_ix = cursor.sum_start().0;
         cursor.seek(&Height(self.scroll_top + height), Bias::Left, &());
         let end_ix = cursor.sum_start().0;
-        start_ix..end_ix + 1
+        start_ix..self.elements.len().min(end_ix + 1)
     }
 
     fn scroll(

zed/src/chat_panel.rs 🔗

@@ -1,31 +1,33 @@
-use super::{
-    channel::{Channel, ChannelList},
-    Settings,
-};
-use gpui::{elements::*, Entity, ModelHandle, RenderContext, View, ViewContext};
-use postage::watch;
+use super::channel::{Channel, ChannelList};
+use gpui::{elements::*, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext};
 
 pub struct ChatPanel {
     channel_list: ModelHandle<ChannelList>,
-    active_channel: Option<ModelHandle<Channel>>,
-    // active_channel_subscription: Subscription,
+    active_channel: Option<(ModelHandle<Channel>, Subscription)>,
     messages: ListState,
 }
 
 pub enum Event {}
 
 impl ChatPanel {
-    pub fn new(
-        channel_list: ModelHandle<ChannelList>,
-        settings: watch::Receiver<Settings>,
-        cx: &mut ViewContext<Self>,
-    ) -> Self {
+    pub fn new(channel_list: ModelHandle<ChannelList>, cx: &mut ViewContext<Self>) -> Self {
         let mut this = Self {
             channel_list,
             messages: ListState::new(Vec::new()),
             active_channel: None,
         };
-        let channel = this.channel_list.update(cx, |list, cx| {
+
+        this.assign_active_channel(cx);
+        cx.observe(&this.channel_list, |this, _, cx| {
+            this.assign_active_channel(cx);
+        })
+        .detach();
+
+        this
+    }
+
+    pub fn assign_active_channel(&mut self, cx: &mut ViewContext<Self>) {
+        let channel = self.channel_list.update(cx, |list, cx| {
             if let Some(channel_id) = list
                 .available_channels()
                 .and_then(|channels| channels.first())
@@ -36,13 +38,17 @@ impl ChatPanel {
             None
         });
         if let Some(channel) = channel {
-            this.set_active_channel(channel);
+            if self.active_channel.as_ref().map(|e| &e.0) != Some(&channel) {
+                let subscription = cx.observe(&channel, Self::channel_did_change);
+                self.active_channel = Some((channel, subscription));
+            }
+        } else {
+            self.active_channel = None;
         }
-        this
     }
 
-    pub fn set_active_channel(&mut self, channel: ModelHandle<Channel>) {
-        //
+    fn channel_did_change(&mut self, _: ModelHandle<Channel>, cx: &mut ViewContext<Self>) {
+        cx.notify();
     }
 }
 
@@ -55,7 +61,7 @@ impl View for ChatPanel {
         "ChatPanel"
     }
 
-    fn render(&self, cx: &RenderContext<Self>) -> gpui::ElementBox {
+    fn render(&self, _: &RenderContext<Self>) -> gpui::ElementBox {
         List::new(self.messages.clone()).boxed()
     }
 }

zed/src/workspace.rs 🔗

@@ -374,14 +374,8 @@ impl Workspace {
         let mut right_sidebar = Sidebar::new(Side::Right);
         right_sidebar.add_item(
             "icons/comment-16.svg",
-            cx.add_view(|cx| {
-                ChatPanel::new(
-                    app_state.channel_list.clone(),
-                    app_state.settings.clone(),
-                    cx,
-                )
-            })
-            .into(),
+            cx.add_view(|cx| ChatPanel::new(app_state.channel_list.clone(), cx))
+                .into(),
         );
         right_sidebar.add_item("icons/user-16.svg", cx.add_view(|_| ProjectBrowser).into());