collab: Reconnect to channel notes (#31950)

Piotr Osiewicz and Kirill Bulatov created

Closes #31758

Release Notes:

- Fixed channel notes not getting re-connected when a connection to Zed
servers is restored.

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>

Change summary

crates/channel/src/channel_buffer.rs | 12 ++++++++++++
crates/channel/src/channel_store.rs  |  5 +++--
crates/collab_ui/src/channel_view.rs |  4 ++++
3 files changed, 19 insertions(+), 2 deletions(-)

Detailed changes

crates/channel/src/channel_buffer.rs 🔗

@@ -35,6 +35,7 @@ pub struct ChannelBuffer {
 pub enum ChannelBufferEvent {
     CollaboratorsChanged,
     Disconnected,
+    Connected,
     BufferEdited,
     ChannelChanged,
 }
@@ -103,6 +104,17 @@ impl ChannelBuffer {
         }
     }
 
+    pub fn connected(&mut self, cx: &mut Context<Self>) {
+        self.connected = true;
+        if self.subscription.is_none() {
+            let Ok(subscription) = self.client.subscribe_to_entity(self.channel_id.0) else {
+                return;
+            };
+            self.subscription = Some(subscription.set_entity(&cx.entity(), &mut cx.to_async()));
+            cx.emit(ChannelBufferEvent::Connected);
+        }
+    }
+
     pub fn remote_id(&self, cx: &App) -> BufferId {
         self.buffer.read(cx).remote_id()
     }

crates/channel/src/channel_store.rs 🔗

@@ -972,6 +972,7 @@ impl ChannelStore {
                                     .log_err();
 
                                 if let Some(operations) = operations {
+                                    channel_buffer.connected(cx);
                                     let client = this.client.clone();
                                     cx.background_spawn(async move {
                                         let operations = operations.await;
@@ -1012,8 +1013,8 @@ impl ChannelStore {
 
                 if let Some(this) = this.upgrade() {
                     this.update(cx, |this, cx| {
-                        for (_, buffer) in this.opened_buffers.drain() {
-                            if let OpenEntityHandle::Open(buffer) = buffer {
+                        for (_, buffer) in &this.opened_buffers {
+                            if let OpenEntityHandle::Open(buffer) = &buffer {
                                 if let Some(buffer) = buffer.upgrade() {
                                     buffer.update(cx, |buffer, cx| buffer.disconnect(cx));
                                 }

crates/collab_ui/src/channel_view.rs 🔗

@@ -354,6 +354,10 @@ impl ChannelView {
                 editor.set_read_only(true);
                 cx.notify();
             }),
+            ChannelBufferEvent::Connected => self.editor.update(cx, |editor, cx| {
+                editor.set_read_only(false);
+                cx.notify();
+            }),
             ChannelBufferEvent::ChannelChanged => {
                 self.editor.update(cx, |_, cx| {
                     cx.emit(editor::EditorEvent::TitleChanged);