This commit is contained in:
2026-07-29 11:15:42 +07:00
parent ef7698d248
commit 5945251a60
4 changed files with 32 additions and 14 deletions

View File

@@ -517,7 +517,7 @@ impl ChatRegistry {
/// Emit an open room event. /// Emit an open room event.
/// ///
/// If the room is new, add it to the registry. /// If the room is new, add it to the registry.
pub fn emit_room(&mut self, room: &Entity<Room>, cx: &mut Context<Self>) { pub fn emit_room(&mut self, room: &Entity<Room>, window: &mut Window, cx: &mut Context<Self>) {
// Get the room's ID. // Get the room's ID.
let id = room.read(cx).id; let id = room.read(cx).id;
@@ -526,14 +526,18 @@ impl ChatRegistry {
self.rooms.insert(0, room.to_owned()); self.rooms.insert(0, room.to_owned());
} }
// Emit the open room event. // Emit the open room event deferred to avoid re-entrant reads
cx.emit(ChatEvent::OpenRoom(id)); cx.defer_in(window, move |_this, _window, cx| {
cx.emit(ChatEvent::OpenRoom(id));
});
} }
/// Close a room. /// Close a room.
pub fn close_room(&mut self, id: u64, cx: &mut Context<Self>) { pub fn close_room(&mut self, id: u64, window: &mut Window, cx: &mut Context<Self>) {
if self.rooms.iter().any(|r| r.read(cx).id == id) { if self.rooms.iter().any(|r| r.read(cx).id == id) {
cx.emit(ChatEvent::CloseRoom(id)); cx.defer_in(window, move |_this, _window, cx| {
cx.emit(ChatEvent::CloseRoom(id));
});
} }
} }

View File

@@ -262,7 +262,11 @@ impl ChatPanel {
this.insert_message(message, false, cx); this.insert_message(message, false, cx);
} }
RoomEvent::Reload => { RoomEvent::Reload => {
this.get_messages(window, cx); // Defer to avoid re-entrant read on Room while
// emit_refresh holds a write lock (via refresh_rooms).
cx.defer_in(window, |this, window, cx| {
this.get_messages(window, cx);
});
} }
}; };
}, },

View File

@@ -221,13 +221,23 @@ impl Workspace {
); );
subscriptions.push( subscriptions.push(
// Observe the chat registry // Observe the chat registry.
// Deferred via spawn to avoid potential re-entrancy if
// cx.observe fires synchronously during a chat.update.
cx.observe(&chat, move |this, chat, cx| { cx.observe(&chat, move |this, chat, cx| {
let ids = this.panel_ids(cx); let ids = this.panel_ids(cx);
let chat = chat.downgrade();
chat.update(cx, |this, cx| { cx.spawn(async move |this, cx| -> anyhow::Result<()> {
this.refresh_rooms(&ids, cx); if let Some(chat) = chat.upgrade() {
}); this.update(cx, |_this, cx| {
chat.update(cx, |chat, cx| {
chat.refresh_rooms(&ids, cx);
});
})?;
}
Ok(())
})
.detach();
}), }),
); );

View File

@@ -329,7 +329,7 @@ impl Sidebar {
.organize(&public_key) .organize(&public_key)
.kind(RoomKind::Ongoing) .kind(RoomKind::Ongoing)
}); });
this.emit_room(&room, cx); this.emit_room(&room, _window, cx);
})?; })?;
// Reset the find panel // Reset the find panel
@@ -373,9 +373,9 @@ impl Sidebar {
let room = item.read(cx); let room = item.read(cx);
let room_clone = item.clone(); let room_clone = item.clone();
let public_key = room.display_member(cx).public_key(); let public_key = room.display_member(cx).public_key();
let handler = cx.listener(move |_this, _ev, _window, cx| { let handler = cx.listener(move |_this, _ev, window, cx| {
ChatRegistry::global(cx).update(cx, |s, cx| { ChatRegistry::global(cx).update(cx, |s, cx| {
s.emit_room(&room_clone, cx); s.emit_room(&room_clone, window, cx);
}); });
}); });